【问题标题】:KVO - observeValueForKeyPath not being calledKVO - 未调用observeValueForKeyPath
【发布时间】:2014-09-29 03:00:08
【问题描述】:

我想做什么的总结。

我的 AppDelegate.h 中有一个名为 mailText 的 NSMutableString 属性,每当我更改此属性的值时,我希望我的 viewController 得到通知,它会将其本地 IBOutlet 属性的值设置为新值。最终,APpDelegate 将根据收到的推送通知更改字符串。

为了进行测试,我在我的 APpDelegate 中触发了一个计时器,并在计时器到期时更改了 mailText 的值。但是,发生这种情况时,不会调用 ViewCONtroller 中的 addObserver 方法

我的 AppDelegate.h 中的代码

@property (strong, nonatomic) NSMutableString *mailText;

AppDelegate.m 中的代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    ......

    self.mailText = [NSMutableString string] ;
    self.mailText = (NSMutableString *)@"First text" ;

    [self enableTimer] ;
    ......
}

-(void) enableTimer
{
    NSTimer *timer = nil ;

    timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:@selector(updateText) userInfo:nil repeats:NO] ;

    //self.myTimer = timer ;

}

-(void) updateText
{
    self.mailText = (NSMutableString *)@"Changed to second text..aaanjanalnal .. jansjanskanska" ;
    NSLog(@"Timer fired...updating mailtext") ;

}

观察:当我在模拟器上运行应用程序时,正在打印 NSLog“计时器触发...”

我的 ViewController.h 中的代码

@interface MailDispViewController : UIViewController

@property (weak, nonatomic) IBOutlet UITextView *mailDispText;

@end

我的 ViewController.m 中的代码

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [(AppDelegate *)[[UIApplication sharedApplication] delegate] addObserver:self forKeyPath:@"mailText" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    NSLog(@"received a KVO") ;

    if ([keyPath isEqual:@"mailText"]) {
        NSLog(@"received a KVO for mailtext") ;
        self.mailDispText.text = [change objectForKey:NSKeyValueChangeNewKey];

     }
    /*
     Be sure to call the superclass's implementation *if it implements it*.
     NSObject does not implement the method.
     */
    [super observeValueForKeyPath:keyPath
                         ofObject:object
                           change:change
                          context:context];
 }

观察:两个 NSLogs “received a KVO”都没有被打印出来。

谁能告诉我我做错了什么?

第二个问题,我如何从 Xcode 的调试窗口中找到 mailText 中存储的值。我试过 po mailText,但没有用。

【问题讨论】:

  • 发现问题...viewDidLoad 未被调用...
  • 在您的-viewDidLoad 中登录。它是在计时器触发之前发生的吗?顺便说一句:您基本上不应该对属性使用可变类型; value 属性应该几乎总是copy 而不是strong;您不能只将字符串文字转换为 NSMutableString* 并期望这会使它们可变;在分配另一个值之前立即将 [NSMutableString string] 分配给属性只会循环。
  • 谢谢肯。我认为您的回答解释了我看到的下一个问题(当我回到主屏幕时崩溃)。你能用初学者的术语解释一下关于可变字符串的部分吗?我是 ObjectiveC 的新手,所有这些 Mutable 的东西对我来说都是新的,因为我以前主要是 C 程序员。当我尝试使用 NSString 时,我得到一个 EXC_BAD_ACCESS,当我尝试在计时器到期后更改值时。那么,如果我不能使用 NSMutableString,我该如何更改字符串的值
  • 更新:将所有内容更改为 NSSTring。仍然遇到同样的问题。如果我单击主视图中的第二个表格单元格并进入 textview 然后返回,则当计时器到期并且 NSString 被覆盖时,会有一个 EXC_BAD_ACCESS 。一问:我需要在初始导航控制器-->表格视图控制器和我的带有TextView的视图控制器之间有一个导航控制器吗?

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


【解决方案1】:

答案是:不要打电话

[super observeValueForKeyPath:keyPath
                         ofObject:object
                           change:change
                          context:context];

当 super 不会处理 keyPath。这意味着无论何时他们的关键路径是你的或上下文是你的,你都不应该调用 super。只调用 super 以确保可以定期观察不来自您的代码的 kvo。

【讨论】:

    【解决方案2】:

    发现了问题:MailDispViewControllerviewDidLoad 从未被调用过,因为我从未涉足此视图。

    【讨论】:

    • 在释放视图控制器之前,您需要删除您在-viewDidLoad 中设置的键值观察。
    • 谢谢,但我想维护 KVO...即,每当 AppDelegate 在有效负载中收到带有新文本的新推送通知时,我希望在我从“主”移动时显示新文本窗口”进入“消息显示窗口”。我应该删除 KVO 并重新添加吗?
    • 如果正在观察的视图控制器有可能被释放,那么您必须删除观察。如果您稍后创建一个新实例,您可以重新添加它,是的。
    • 谢谢,非常有帮助的东西。将删除代码放入 ViewDidDisappear 是否足以捕获所有“解除分配”案例?
    • 我不知道。我不做 iOS 开发。
    猜你喜欢
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 2011-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多