【问题标题】:KVO and refactoringKVO 和重构
【发布时间】:2013-01-16 12:25:38
【问题描述】:

假设我有:

@property NSNumber* number;

我的控制器正在观察:

- (void)observeValueForKeyPath:(NSString *)keyPath ...
{
    if ([keyPath isEqualToString:@"number"]) ...
}

我的问题是 - 你重构number属性名称的方法是什么

很明显,我需要更新观察者代码中的观察键,但我怎样才能以某种智能/自动的方式进行更新,并且不会错过任何观察者来处理我的属性更改?

【问题讨论】:

  • 你想重构什么?我什至没有看到实际的代码做某事。
  • 对不起,我刚刚更新了我的意思是重命名属性并更新观察到的 keyPath 名称

标签: ios objective-c properties refactoring key-value-observing


【解决方案1】:

一种方法是为所有被观察的属性声明字符串常量。使用这些常量添加观察者和比较keypath。每当您想重命名属性时,都应该更改这些字符串常量的值。

我认为完全雾化是不可能的。

【讨论】:

  • 另一种方法是使用反射。如果已确定您的属性数量及其在类中的顺序不会改变,您可以借助运行时函数,例如访问特定索引的属性。
【解决方案2】:

好的,我会回复自己的:)我的解决方案是 Apurv 解决方案和单元测试的混合体。

这里是:

1 对于MyClass 中的每个观察到的属性,定义:

static NSString* MyClassPropertyNameNumber = @"number";

2- (void)observeValueForKeyPath:(NSString *)keyPath ... 实现中使用定义的NSStrings。

- (void)observeValueForKeyPath:(NSString *)keyPath ...
{
    if ([keyPath isEqualToString:MyClassPropertyNameNumber]) ...
}

3 编写单元测试,检查 MyClass 对象是否响应 setNumber:number 选择器。

- (void)testMyClass
{
    SEL numberGetter = NSSelectorFromString(MyClassPropertyNameNumber);
    SEL numberSetter = NSSelectorFromString([NSString stringWithFormat:@"set%@:", MyClassPropertyNameNumber]);
    
    MyClass* testMyClass = [[MyClass alloc] init];
    if (![testMyClass respondsToSelector:numberGetter] || ![testMyClass respondsToSelector:numberSetter])
    {
        STFail(@"%@: %@ property name has changed! Please update your defined property name!", NSStringFromClass([MyClass class]), MyClassPropertyNameNumber);
    }
}

如果您更改属性名称,并且不更新定义的属性名称,它将失败。

我希望它对某人有帮助:)

【讨论】:

    【解决方案3】:

    为每个观察到的键路径定义一个变量,在注册时和在观察者处理程序方法中使用它们作为上下文:

    static void * numberKVO = &numberKVO;
    static void * letterKVO = &letterKVO;
    
    ...
    [self addObserver:self 
           forKeyPath:@"kp.4.number" 
              options:NSKeyValueObservingOptionNew 
              context:numberKVO];
    [self addObserver:self 
           forKeyPath:@"kp.4.letter" 
              options:NSKeyValueObservingOptionNew 
              context:letterKVO];   
    ...
    
    - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        if (context == numberKVO) {
            ...
        } else if (context == letterKVO) {
            ...
        }
    }
    

    您可以修改属性和键路径,而无需更改任何其他内容。

    【讨论】:

      【解决方案4】:

      Mogenerator 是处理 Core Data 模型类的好工具。它为所有属性、关系和获取的属性生成 NSString:

      extern const struct ModelClassAttributes
      extern const struct ModelClassRelationships
      extern const struct ModelClassFetchedProperties
      

      【讨论】:

        猜你喜欢
        • 2023-03-19
        • 1970-01-01
        • 2011-08-17
        • 1970-01-01
        • 2011-08-08
        • 2011-09-27
        • 1970-01-01
        • 1970-01-01
        • 2011-04-13
        相关资源
        最近更新 更多