美文网首页
[iOS][OC] 复写 delegate accessors

[iOS][OC] 复写 delegate accessors

作者: BudSwift | 来源:发表于2018-11-08 08:42 被阅读21次

委托模式是 iOS 开发常用的设计模式,在实现当中必要时可以做一些小优化:

  • 设置 delegate 后,即需要向 delegate 获取数据或发送消息,复写 setter:
- (void)setDelegate:(id<SomeProtocol>delegate {
    _delegate = delegate;
    // do something if needed.
}
  • 协议的 optional 方法众多,每次都判断 respondsToSelector: 会比较繁琐,提供一个便利方法:
- (BOOL)delegate_respondsToSelector:(SEL)selector {
    return self.delegate && [self.delegate respondsToSelector:selector];
}
  • 进一步地,如果业务中有多处需要判断 delegate_respondsToSelector: 那么不妨将这个业务独立成一个方法来处理,比如 DZNEmptyDataSet 的处理方式:
- (void)dzn_willDisappear
{
    if (self.emptyDataSetDelegate && [self.emptyDataSetDelegate respondsToSelector:@selector(emptyDataSetWillDisappear:)]) {
        [self.emptyDataSetDelegate emptyDataSetWillDisappear:self];
    }
}
  • 再进一步的,如果是在 category 中新增了一个 delegate 对象,使用了 Runtime 的 objc_setAssociatedObject 函数进行关联,那么使用 assign 策略(因为没有 weak 策略)来实现就有潜在发生野指针异常的情况(见前文分析《[iOS] 从 application.delegate 引申三点》)。从 DZNEmptyDataSet 可以学习到 delegate 直接使用 retain 策略,不过 retain 的对象是一个 DZNWeakContainer,使用 container 对 delegate 进行 weak 引用,解决了 association 场景下的 assign 野指针问题。
- (void)setEmptyDataSetSource:(id<DZNEmptyDataSetSource>)datasource {
    ....
        objc_setAssociatedObject(self,
                             kEmptyDataSetSource,
                             [[DZNWeakObjectContainer alloc] initWithWeakObject:datasource],
                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
     ....
}

@interface DZNWeakObjectContainer : NSObject

@property (nonatomic, readonly, weak) id weakObject;

- (instancetype)initWithWeakObject:(id)object;

@end

@implementation DZNWeakObjectContainer

- (instancetype)initWithWeakObject:(id)object
{
    self = [super init];
    if (self) {
        _weakObject = object;
    }
    return self;
}

@end

对应的调整 getter 方法:

- (id<DZNEmptyDataSetDelegate>)emptyDataSetDelegate
{
    DZNWeakObjectContainer *container = objc_getAssociatedObject(self, kEmptyDataSetDelegate);
    return container.weakObject;
}
  • 如果自身要成为自身的 delegate 时,则更有必要进行处理了,这部分分析可以学习 文本输入限制框架 InputKit 的使用,以及开发者介绍的文章 self.delegate = self?

如果同时复写了 setter/getter,那么就意味着不需要自动合成属性变量,需要手动合成。

@synthesize delegate = _delegate;

参考:

加我微信沟通。


相关文章

网友评论

      本文标题:[iOS][OC] 复写 delegate accessors

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