iOS Aspects 使用-坑点

Aspects https://github.com/steipete/Aspects
常用的viewDidLoad 拦截添加统计事件需求很多,因为不需要改变原本viewDidLoad事件,介绍一下另两个需求.

  • 拦截修改次方法,
[UIImage imageNamed:@"ax_icon_weixin"]

返回

[UIImage imageNamed:@"chongshe"]

注意 imageNamed是+方法,所以需要用object_getClass(UIImage.class)

        NSError *error;
        [object_getClass(UIImage.class) aspect_hookSelector:@selector(imageNamed:) withOptions:AspectPositionAfter usingBlock:^(id aspectInfo,NSString *imageNamed) {
            NSInvocation  *invocation = aspectInfo.originalInvocation;
            if ([aspectInfo.arguments.firstObject isEqualToString:@"ax_icon_weixin"]) {
                id img= nil;
                img= [UIImage imageNamed:@"chongshe"];
                [invocation setReturnValue:&img];
                NSLog(@"img %@",img);
            }
        } error:&error];
        NSLog(@"ax_imageNamed error== %@",error);
  • 在修改app icon时候,取消弹窗代码,用Aspects 实现
- (void)setIconname:(NSString *)name {
    UIApplication *appli = [UIApplication sharedApplication];
    //判断系统是否支持切换icon
    if (@available(iOS 10.3, *)) {
        if ([appli supportsAlternateIcons]) {
            //切换icon
            [appli setAlternateIconName:name completionHandler:^(NSError * _Nullable error) {
                if (error) {
                    NSLog(@"error==> %@",error.localizedDescription);
                }else{
                    NSLog(@"done!!!");
                }
            }];
        }
    } else {
        // Fallback on earlier versions
    }
}

自定义拦截方法

 static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method presentM = class_getInstanceMethod(self.class, @selector(presentViewController:animated:completion:));
        Method presentSwizzlingM = class_getInstanceMethod(self.class, @selector(dy_presentViewController:animated:completion:));
        // 交换方法实现
        method_exchangeImplementations(presentM, presentSwizzlingM);
    });
- (void)dy_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
    
    if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
        NSLog(@"title : %@",((UIAlertController *)viewControllerToPresent).title);
        NSLog(@"message : %@",((UIAlertController *)viewControllerToPresent).message);
        
        UIAlertController *alertController = (UIAlertController *)viewControllerToPresent;
        
        if (alertController.title == nil && alertController.message == nil) {
            return;
        } else {
            [self dy_presentViewController:viewControllerToPresent animated:flag completion:completion];
            return;
        }
    }
    
    [self dy_presentViewController:viewControllerToPresent animated:flag completion:completion];
}

用Aspects 实现

    /// usingBlock: 第一个参数 调用对象,第二个是方法的第一次参数
     [UIViewController aspect_hookSelector:@selector(presentViewController:animated:completion:) withOptions:AspectPositionInstead usingBlock:^(id aspectInfo,UIViewController *presentViewController) {
         /// aspectInfo.arguments.firstObject 就是 presentViewController
         if (![presentViewController isKindOfClass:[UIAlertController class]]) {
             [aspectInfo.originalInvocation invoke];
         }else{
             UIAlertController *alertController = (UIAlertController *)presentViewController;
            /// 这里用 == nil ,不要用length==0,业务需求不一样
             if (alertController.title != nil || alertController.message != nil) {
                 [aspectInfo.originalInvocation invoke];
             }
         }
     } error:nil];

你可能感兴趣的:(iOS Aspects 使用-坑点)