问题描述
在 键值观察编程指南,部分 Registering for Key-Value Observing 说Apple 提供的框架中的典型属性只有在记录为 KVO 时才符合 KVO."但是,我没有在文档中找到任何符合 KVO 的属性.请给我指点一下好吗?
In the Key-Value Observing Programming Guide, the section Registering for Key-Value Observing says "Typically properties in Apple-supplied frameworks are only KVO-compliant if they are documented as such." But, I haven't found any properties in the documentation that are documented as KVO-compliant. Would you please point me to some?
具体来说,我想知道 UIWindow
的 @property(nonatomic,retain) UIViewController *rootViewController
是否符合 KVO.原因是我将 rootViewController
属性添加到 UIWindow
for iOS <4 并且想知道我是否应该使其符合 KVO.
Specifically, I would like to know if the @property(nonatomic,retain) UIViewController *rootViewController
of UIWindow
is KVO-compliant. The reason is that I'm adding the rootViewController
property to UIWindow
for iOS < 4 and want to know if I should make it KVO-compliant.
@interface UIWindow (Additions)
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0
@property (nonatomic, retain) UIViewController *rootViewController;
#endif;
@end
@implementation UIWindow (Additions)
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0
@dynamic rootViewController;
- (void)setRootViewController:(UIViewController *)newRootViewController {
if (newRootViewController != _rootViewController) {
// Remove old views before adding the new one.
for (UIView *subview in [self subviews]) {
[subview removeFromSuperview];
}
[_rootViewController release];
_rootViewController = newRootViewController;
[_rootViewController retain];
[self addSubview:_rootViewController.view];
}
}
#endif
@end
推荐答案
简答:没有.
长答案:UIKit 中的任何内容都不能保证符合 KVO.如果您碰巧发现 KVO-ing 属性有效,请不胜感激,这是无意的.还有:小心.将来很可能会崩溃.
Long answer: Nothing in UIKit is guaranteed to be KVO-compliant. If you happen to find that KVO-ing a property works, be grateful, it's unintentional. Also: be wary. It could very well break in the future.
如果您发现这是您需要的,请提交增强请求.
If you find that this is something you need, please file an enhancement request.
关于您的实际代码,它本身就有缺陷.NOT 尝试以这种方式将rootViewController"设置器添加到 UIWindow
.当您在 iOS 4 上编译代码但有人在 iOS 5 设备上运行它时,它会中断.因为您使用 4.x SDK 编译,所以 #if
语句将评估为 true,这意味着您的类别方法粉碎器将包含在二进制文件中.但是,当您在 iOS 5 设备上运行它时,您现在会遇到方法冲突,因为 UIWindow
上的两个方法将具有相同的方法签名,并且 无法保证将使用哪一个.
About your actual code, it's inherently flawed. Do NOT attempt to add a "rootViewController" setter to UIWindow
this way. It will break when you compile your code on iOS 4 but someone runs it on an iOS 5 device. Because you compiled using the 4.x SDK, the #if
statements will evaluate to true, meaning your category method smasher will be included in the binary. However, when you run it on an iOS 5 device, you're now going to get a method conflict because two methods on UIWindow
will have the same method signature, and there's no guarantee as to which one will be used.
不要搞砸这样的框架.如果您必须拥有它,请使用子类.这就是子类存在的原因.
Don't screw with the frameworks like this. If you have to have this, use a subclass. THIS IS WHY SUBCLASSING EXISTS.
你的子类看起来像这样:
Your subclass would look something like this:
@interface CustomWindow : UIWindow
@property (nonatomic, retain) UIViewController *rootViewController;
@end
@implementation CustomWindow : UIWindow
static BOOL UIWindowHasRootViewController = NO;
@dynamic rootViewController;
- (void)_findRootViewControllerMethod {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
IMP uiwindowMethod = [UIWindow instanceMethodForSelector:@selector(setRootViewController:)];
IMP customWindowMethod = [CustomWindow instanceMethodForSelector:@selector(setRootViewController:)];
UIWindowHasRootViewController = (uiwindowMethod != NULL && uiwindowMethod != customWindowMethod);
});
}
- (UIViewController *)rootViewController {
[self _findRootViewControllerMethod];
if (UIWindowHasRootViewController) {
// this will be a compile error unless you forward declare the property
// i'll leave as an exercise to the reader ;)
return [super rootViewController];
}
// return the one here on your subclass
}
- (void)setRootViewController:(UIViewController *)rootViewController {
[self _findRootViewControllerMethod];
if (UIWindowHasRootViewController) {
// this will be a compile error unless you forward declare the property
// i'll leave as an exercise to the reader ;)
[super setRootViewController:rootViewController];
} else {
// set the one here on your subclass
}
}
这篇关于iOS:我如何知道某个属性是否符合 KVO?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!