用block代替@selector

作者: HJaycee | 来源:发表于2017-04-28 14:52 被阅读302次

    一般给按钮添加事件是这样的组合:

    // 把点击后要调用的方法名传到@selector中
    self.btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
    
    // 找别的地方写上方法的实现
    - (void)btnClick {
    }
    

    这样写代码多不说,工程大的话还得到处找方法。
    所以我写了一个分类,可以用block来代替@selector(),防止代码分散。

    使用起来是这样的:

    // button
    [self.btn addTarget:self action:[self selectorBlock:^(id arg) {
        NSLog(@"clicked %@", arg);
    }] forControlEvents:UIControlEventTouchUpInside];
    

    下面讲一下分类NSObject+BlockSEL.h中的实现原理

    - (SEL)selectorBlock:(void (^)(id))block {
        NSString *selName = [NSString stringWithFormat:@"selector_%p:", block];
        SEL sel = NSSelectorFromString(selName);
        class_addMethod([self class], sel, (IMP)selectorImp, "v@:@");
        objc_setAssociatedObject(self, sel, block, OBJC_ASSOCIATION_COPY_NONATOMIC);
        return sel;
    }
    
    static void selectorImp(id self, SEL _cmd, id arg) {
        void (^block)(id arg) = objc_getAssociatedObject(self, _cmd);
        if (block) block(arg);
    }
    

    block的内存地址创建一个唯一方法,并将方法实现绑定到selectorImp函数。将block用关联对象保存下来,在调用时执行block

    需要注意一下,当block中使用self时会产生循环引用,需要用__weak来修饰防止self无法释放。

    __weak typeof(self) weakSelf = self;
    [self.btn addTarget:self action:[self selectorBlock:^(id arg) {
        weakSelf.view.backgroundColor = [UIColor whiteColor];
    }] forControlEvents:UIControlEventTouchUpInside];
    

    demo下载地址

    相关文章

      网友评论

        本文标题:用block代替@selector

        本文链接:https://www.haomeiwen.com/subject/ttzozttx.html