objective-c - iOS:我如何知道一个属性是否符合 KVO 标准?

标签 objective-c ios cocoa-touch ios4 key-value-observing

Key-Value Observing Programming Guide , 第 Registering for Key-Value Observing说“通常情况下,Apple 提供的框架中的属性只有在被记录为这样的情况下才符合 KVO。”但是,我没有在文档中找到任何被记录为符合 KVO 的属性。你能给我指出一些吗?

具体来说,我想知道 UIWindow@property(nonatomic,retain) UIViewController *rootViewController 是否符合 KVO。原因是我将 rootViewController 属性添加到 UIWindow for iOS < 4 并想知道我是否应该使其符合 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

最佳答案

简短的回答:没有。

长答案:UIKit 中的任何内容都不能保证符合 KVO。如果你碰巧发现 KVO-ing 一个属性有效,感激不尽,这是无意的。另外:要小心。它很可能在未来破裂。

如果您发现这是您需要的东西,请file an enhancement request .


关于您的实际代码,它存在固有缺陷。 不要尝试以这种方式将“rootViewController”setter 添加到UIWindow。当您在 iOS 4 上编译代码但有人在 iOS 5 设备上运行它时,它中断。因为您使用 4.x SDK 进行编译,所以 #if 语句的计算结果为真,这意味着您的类别方法 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
  }
}

Caveat Implementor:我在浏览器窗口中输入了这个

关于objective-c - iOS:我如何知道一个属性是否符合 KVO 标准?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6612523/

相关文章:

objective-c - CGSizeMake 不适用于常量

ios - 寻找仅用于直接上/下左/右方向的操纵杆

iphone - 使用 iPhone API 拍照并将其传输到服务器

iphone - 我如何在 cocos2d iphone 中存储带有名字的前 5 名分数

iphone - 扩展 NSManagedObject 实体对象是否安全

iphone - 使用 Storyboard时如何获取指向 appDelegate 内的 viewController 的指针

ios - 如何为现有的 iOS 应用程序添加 CarPlay 支持?

ios - 无法设置带有搜索栏显示颜色的搜索栏 iOS7

ios - 根据 subview 的宽高比使父 View 的高度灵活

ios - 同意 Xcode/iOS 许可证需要管理员权限,请通过 sudo 以 root 身份重新运行