[英]How do I cleanly override a property setter?
If I want to define a custom UIView subclass that does something when its bounds are set, how do I override the setter? 如果我想定义一个自定义的UIView子类,它在设置边界时做了什么,我该如何覆盖setter? Overriding setBounds seems dangerous since, if I understand correctly, the getter and setter names are not part of the public interface and could change anytime.
覆盖setBounds似乎很危险,因为如果我理解正确,getter和setter名称不是公共接口的一部分,并且可能随时更改。
Of course, I use class_copyPropertyList to query the runtime for a list of properties defined in the class, then query it for the setter's name, and finally use class_addMethod to add the method, after first getting a reference to the earlier method to use for calling the original version. 当然,我使用class_copyPropertyList在运行时查询类中定义的属性列表,然后查询它以获取setter的名称,最后使用class_addMethod添加方法,首先获取对用于调用的早期方法的引用原始版本。
All this seems hacky. 这一切看起来都很糟糕。 Is there a clean way to do what I want, which is guaranteed to not break on future OS versions?
是否有一种干净的方式来做我想要的,保证在未来的操作系统版本上不会中断? Thanks.
谢谢。
You can override a setter/getter without having to poke around the internal state of the class (ie ivars) -- just call the super's methods in your overrides: 你可以覆盖一个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];
}
An alternative that might suit your problem is to use KVO . 可能适合您的问题的替代方案是使用KVO 。
Update 更新
Of course, overriding setBounds
might not be necessary. 当然,可能没有必要覆盖
setBounds
。 See this question -- layoutSubviews
gets called if the frame changes, and changing the bounds causes the frame size to also be updated. 看到这个问题 - 如果帧更改,则调用
layoutSubviews
,并且更改边界会导致帧大小也更新。 So consider putting your code into layoutSubviews
. 因此,请考虑将您的代码放入
layoutSubviews
。
Final update 最后更新
Ok, here is why Apple is never going to suddenly declare some @property
items as using a non-standard method names (as you fear): 好的,这就是为什么Apple永远不会突然将某些
@property
项目声明为使用非标准方法名称(如您所愿):
It would break everything in the app store. 它会破坏应用商店中的所有内容。
Think about it this way: at compile time, any code that accesses a property using dot notation, eg the obj.x
syntactic sugar, is converted to a message of the form [obj x]
. 可以这样考虑:在编译时,使用点表示法访问属性的任何代码(例如
obj.x
语法糖)都将转换为[obj x]
形式的消息。 Likewise for properties -- they are converted at compile time into regular methods. 同样对于属性 - 它们在编译时转换为常规方法。 So, compiled binaries know nothing about dot notation and properties -- they just call regular selectors.
因此, 编译后的二进制文件对点表示法和属性一无所知 - 它们只调用常规选择器。 So if Apple released an update to iOS that declared some public properties as having non-standard implementation methods, everything in the app store could break.
因此,如果Apple发布iOS更新,声称某些公共属性具有非标准实现方法,那么应用商店中的所有内容都可能会中断。 Everything.
一切。 There is no fault on your behalf in this scenario if your app broke like the rest -- it would be Apple's fault, not yours.
如果您的应用程序像其他应用程序一样崩溃,那么在这种情况下您没有任何错误 - 这将是Apple的错,而不是您的错。
@property(nonatomic) CGRect bounds;
is shorthand for 是简写
-(CGRect)bounds;
-(void)setBounds:(CGRect)bounds;
, ,
view.bounds = rect;
is shorthand for 是简写
[view setBounds:rect];
, ,
CGRect rect = view.bounds;
is shorthand for 是简写
CGRect rect = [view bounds];
Dot notation and @property declarations are SYNTACTIC SUGAR. 点符号和@property声明是SYNTACTIC SUGAR。 They are for shortening code and convenience.
它们用于缩短代码和方便性。 Messages and selectors are always always underneath them, and can always be relied on to be a stable, if not the most stable, part of the interface.
消息和选择器总是位于它们之下,并且始终可以依赖于接口的稳定(如果不是最稳定)部分。
Overriding "setBounds:" is a safe way to do this. 覆盖“setBounds:”是一种安全的方法。 "setBounds:" is not explicitly named in the public interface, because it is declared as a @property.
“setBounds:”未在公共接口中显式命名,因为它被声明为@property。 However the standard is that the setter with "set"-capitalized property name is always created (unless its readonly).
但是标准是始终创建具有“set”-capitalized属性名称的setter(除非是readonly)。
There is an NSViewBoundsDidChange notification in OSX. OSX中有一个NSViewBoundsDidChange通知。 That does appear to be the better solution, although fears of overriding the @property methods seem unfounded.
这似乎是更好的解决方案,尽管对覆盖@property方法的担忧似乎没有根据。 I happened on this post with the same question about overriding the accessors, and you have convinced me to prefer notifications.
我在这篇文章中遇到了关于覆盖访问者的相同问题,你说服我更喜欢通知。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.