如何干净地覆盖属性设置器?

Vad*_*ick 6 iphone cocoa cocoa-touch uikit ios

如果我想定义一个自定义的UIView子类,它在设置边界时做了什么,我该如何覆盖setter?覆盖setBounds似乎很危险,因为如果我理解正确,getter和setter名称不是公共接口的一部分,并且可能随时更改.

当然,我用class_copyPropertyList查询运行时在类中定义的属性列表,然后查询它的setter的名字,最后用class_addMethod添加的方法,在第一次得到一个参考前面的方法使用调用原始版本.

这一切看起来都很糟糕.是否有一种干净的方式来做我想要的,保证在未来的操作系统版本上不会中断?谢谢.

occ*_*lus 19

你可以覆盖一个setter/getter,而不必嘲笑类的内部状态(即ivars) - 只需在你的覆盖中调用super的方法:

- (Thing *)thing {
    // do your extra stuff here
    //  ...

    return [super thing];
}

- (void)setThing:(Thing *)thing {
    // do your extra stuff here
    //  ...

    [super setThing:thing];
}
Run Code Online (Sandbox Code Playgroud)

可能适合您的问题的替代方案是使用KVO.

更新

当然,setBounds可能没有必要覆盖.看到这个问题 - layoutSubviews如果帧发生变化则调用,并且更改边界会导致帧大小也被更新.所以考虑将代码放入layoutSubviews.

最后更新

好的,这就是为什么Apple永远不会突然将某些@property项目声明为使用非标准方法名称(如您所愿):

它会破坏应用商店中的所有内容.

可以这样考虑一下:在编译时,任何使用点表示法访问属性的代码(例如obj.x语法糖)都会转换为表单的消息[obj x].同样对于属性 - 它们在编译时转换为常规方法.因此,编译后的二进制文件对点表示法和属性一无所知 - 它们只调用常规选择器.因此,如果Apple发布iOS更新,声称某些公共属性具有非标准实现方法,那么应用商店中的所有内容都可能会中断.一切.如果您的应用程序像其他应用程序一样崩溃,那么在这种情况下您没有任何错误 - 这将是Apple的错,而不是您的错.