【问题标题】:iPhone KVO between two classes两个类之间的 iPhone KVO
【发布时间】:2011-05-08 02:57:36
【问题描述】:

我的应用程序类 A 和 B 中有两个类。A 类和 B 类都是 UIViewController 的实例。 A 类有一个按钮,当按下该按钮时,会将 B 类推入堆栈。 B 类有一个字符串,A 类想要观察并根据需要更新它的接口。我已经能够使用: [self addObserver:self forKeyPath:@"name" options:0 context:NULL]; 在 B 类中查看对字符串的更改。 当我尝试在 A 类 viewWillAppear 方法中使用以下内容时:

ClassB *b = [[ClassB alloc]init];
[b addObserver:self forKeyPath:@"name" options:0 context:NULL];

并添加方法:

(void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object
                      change:(NSDictionary )change
                     context:(void )context

尝试从 A 查看在 B 中所做的更新时不会触发任何操作。我觉得问这个问题很愚蠢,但是 KVO 在 iOS 中的两个类之间如何工作?我知道这应该可行。

【问题讨论】:

    标签: iphone ios key-value-observing


    【解决方案1】:

    您可以观察不同对象/类之间的变化。我认为问题出在addObserver:forKeyPath:options:context:的options参数中。

    您想要进行的观察类型有多种选择。 KVO Guide 是一个很好的起点,但您可能需要NSKeyValueObservingOptionNew,我在下面的示例中使用它。

    首先,“name”应该是 ClassB 中的公共属性。

    其次,您可能不需要在 ClassA 中的 viewWillAppear 中将观察者添加到“b”,因为您不需要在每次出现 ClassA 视图时都添加它。您只需要在创建 ClassB 视图时添加一次观察者。添加观察者后,observeValueForKeyPath:ofObject:change:context: 方法将在 ClassA 中执行,因此您可以从那里更新 ClassA UI。每次 ClassA 即将出现时,您都不需要做任何事情。

    在 Class A 中,您可能应该在将 ClassB 推送到控制器堆栈之前创建 ClassB,大概是在用户执行的某些操作的事件处理程序中。创建 ClassB 后,立即在 ClassA 中添加具有正确 NSKeyValueObservingOption 值的观察者。

    如果您只想在 ClassB 中的公共属性“名称”发生更改时收到通知,请尝试以下操作:

    B类

    @interface ClassB : UIViewController {
    }
    
    @property (retain) NSString* name;
    
    - (void) aMethodThatModifiesName:(NSString*)newName;
    
    @end
    
    
    @implementation ClassB 
    
    @synthesize name;
    
    - (void) aMethodThatModifiesName:(NSString*)newName {
        // do some stuff
        self.name = newName;
    }
    
    @end
    

    A类

    @interface ClassA : UIViewController {
    }
    
    @property (nonatomic, retain) IBOutlet UILabel* nameLabel;
    
    - (IBAction) someEventHandler:(id)sender;
    
    @end
    
    @implementation ClassA
    
    - (IBAction) someEventHandler:(id)sender {
        ClassB* b = [[ClassB alloc]init];
        [b addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:NULL];
        [self.navigationController pushViewController:b animated:YES];
        [b release];
    }
    
    - (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {
        if ([keyPath isEqual:@"name"]) {
            NSString* changedName = [change objectForKey:NSKeyValueChangeNewKey];
            // do something with the changedName - call a method or update the UI here
            self.nameLabel.text = changedName;
        }
    }
    
    @end
    

    【讨论】:

    • 这可能是问题所在。您需要使用 options 参数来指示您想要什么通知。通过传入 0,您不会要求收到任何通知。
    • 如果这对任何人都有帮助,我遇到了一个问题,即我的 observeValueForKeyPath 消息没有触发,即使我写出来的内容几乎与 nekno 完全相同。您必须使用 self.name = newvalue 更改属性,NOT 只需 name = newvalue。
    • 感谢您指出 Mirkules。似乎必须通过调用 setter 方法来更改观察值。但是观察只读属性的变化又如何呢?
    • @ChristophHalang 在头文件中的接口中将属性声明为只读,然后在主文件的接口扩展中将其重新声明为读写。然后,您可以在主文件中使用设置器,但不能在主文件之外使用。不幸的是,如果您想让人们远离您的班级,这并不是真正的防弹,因为您的只读 ivars 具有可以在运行时检查和调用的设置器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 2019-08-25
    • 2019-03-30
    • 1970-01-01
    • 2012-09-06
    • 2013-01-17
    • 1970-01-01
    相关资源
    最近更新 更多