In the 键值观察编程指南 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html, 这部分注册键值观察 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVOBasics.html说:“通常,Apple 提供的框架中的属性只有在被记录为 KVO 的情况下才符合 KVO。”但是,我在文档中没有找到任何记录为符合 KVO 的属性。请你指点我一些吗?
具体来说,我想知道是否@property(nonatomic,retain) UIViewController *rootViewController
of UIWindow
符合 KVO 标准。原因是我要添加rootViewController
财产给UIWindow
对于 iOS
@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 属性有效,请感激不尽,这是无意的。另外:要小心。未来它很可能会破裂。
如果您发现这是您需要的,请提出增强请求 http://bugreport.apple.com.
关于您的实际代码,它本质上是有缺陷的。做NOT尝试添加“rootViewController”设置器UIWindow
这边走。它will当您在 iOS 4 上编译代码但有人在 iOS 5 设备上运行它时,就会中断。因为您使用 4.x SDK 进行编译,#if
语句将评估为 true,这意味着您的类别方法粉碎器将包含在二进制文件中。但是,当您在 iOS 5 设备上运行它时,您现在会遇到方法冲突,因为两个方法UIWindow
将具有相同的方法签名,并且无法保证将使用哪一个.
不要像这样搞乱框架。如果必须有这个,请使用子类。这就是子类化存在的原因。
你的子类看起来像这样:
@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
}
}
Caveat Implementor: I typed this in a browser window
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)