iOS:我如何知道一个属性是否符合 KVO? [英] iOS: How do I know if a property is KVO-compliant?

查看:29
本文介绍了iOS:我如何知道一个属性是否符合 KVO?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

键值观察编程指南,部分 注册 Key-Value Observing 说通常,Apple 提供的框架中的属性只有在记录时才符合 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.

关于您的实际代码,它本质上是有缺陷的.不要不要尝试以这种方式向UIWindow 添加rootViewController"setter.当您在 iOS 4 上编译代码但有人在 iOS 5 设备上运行它时,它中断.因为您使用 4.x SDK 进行编译,#if 语句将评估为真,这意味着您的类别方法 smasher 将包含在二进制文件中.但是,当您在 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
  }
}

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

Caveat Implementor: I typed this in a browser window

这篇关于iOS:我如何知道一个属性是否符合 KVO?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆