iOS:我如何知道某个属性是否符合KVO标准?

ma1*_*w28 18 cocoa-touch objective-c key-value-observing ios4 ios

Key-Value Observing Programming Guide中,注册键值观察部分说:"Apple提供的框架中的典型属性只有符合KVO标准才会被记录." 但是,我没有在文档中找到任何记录为KVO兼容的属性.你能指点一下吗?

具体来说,我想知道,如果@property(nonatomic,retain) UIViewController *rootViewControllerUIWindow是国际志愿者组织兼容.原因是我正在为iOS <4 添加rootViewController属性,UIWindow并想知道我是否应该使其符合KVO标准.

@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
Run Code Online (Sandbox Code Playgroud)

Dav*_*ong 20

简答:不.

答案很长:UIKit中的任何内容都不能保证符合KVO标准.如果您碰巧发现KVO-ing房产有效,请感激,这是无意的.另外:要小心.它可能在未来很好地打破.

如果您发现这是您需要的,请提交增强请求.


关于你的实际代码,它本质上是有缺陷的.千万不要尝试在"RootViewController的"二传手添加到UIWindow这种方式.当你在iOS 4上编译代码时它破坏,但有人在iOS 5设备上运行它.因为您使用4.x SDK编译,所以#if语句将评估为true,这意味着您的类别方法smasher将包含在二进制文件中.但是,当您在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
  }
}
Run Code Online (Sandbox Code Playgroud)

警告执行者:我在浏览器窗口中输入了这个