- 编辑,请参阅下面的更新解决方案
我在这里有一个应用程序,我在后台线程中下载了一些数据。
每次下载5个项目,在我的主视图控制器中,我发布了一个已下载5个项目的通知。
在我的其他4个视图控制器中,它们本身就是导航堆栈上的根视图控制器,我会深入查看详细信息页面。 (典型的5个标签栏界面)
此详细信息页面是另一个View Controller,我在其中为viewDidLoad方法完成了NSNotificationCenter defaultCenter addObserver。
这里的问题是,当通知发布时,我的详细信息页面的根视图控制器会收到通知,但详细信息页面本身不会收到通知。
虽然我的数据是在后台线程中下载的,但我使用调度方法调用performSelectorOnMainThread :.在调度方法中,它调用[[NSNotificationCenter defaultCenter] postNotificationNamed:object:];
所以:
.... downloading batches of 5 items in a background thread ....
...
... downloaded calling [self performSelectorOnMainThread:@selector(foo) WithObject:nil WaitUntilDone:NO]; ...
...
// foo method
-(void)foo
{
// theoretically, this notification should be delivered and received in the main thread since this foo() method is told to execute on the main thread above
[[NSNotificationCenter defaultCenter] postNotificationName:@"notif_batchDownloaded" object:nil];
}
...
我在根视图控制器中收到通知,但没有收到我的详细信息页面。
1)当下载过程开始时,我已经查看了详细信息页面,所以没有,我认为详细信息页面视图控制器没有被释放
2)详细信息页面视图控制器显然是在主线程上观察通知,如上所述,通知被告知要在主线程上发布。
所以问题是,是否有任何其他原因导致子级视图控制器无法接收通知?
我认为我没有超出任何通知观察员限制。我甚至评论了其他通知,但没有任何区别。
每次下载5个项目时都会发送通知,因此在发送通知之前我无法查看详细信息页面。即使我以某种方式错过了前5,我至少应该获得第2,第5,第5,第4等等。
可能是根视图控制器首先收到通知,然后无法将通知传递给其子级视图控制器?
我没有想法。
我终于找到了它破碎的地方。什么是PITA。
在我以前的viewDidLoad方法中,我就是这样:
-(void)viewDidLoad
{
...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) name:@"notif_batchDownloaded" object:@"notif_batchDownloaded"];
...
}
这里的问题是我传入的“对象”参数。我使用通知的名称作为“对象”字段的参数,但这会导致我的doSomething()方法永远不会被执行。
我删除了对象参数,现在它可以正常工作。
新的viewDidLoad()应该是这样的:
-(void)viewDidLoad
{
...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) name:@"notif_batchDownloaded" object:nil];
...
}
我原本以为我可以像某种标记一样使用“object”参数来帮助我的回调方法识别在我将多个通知发送到同一回调方法的情况下发送了哪个通知。
快速阅读Apple文档显示,object参数用于识别观察者从哪个对象观察通知。即多个对象可以发送相同的通知,此对象参数字段标识它希望仅从哪个对象接收通知。
E.g。
查看控制器A和视图控制器B的postNotificationName:@“notif_foo”。
View Controller C将自身添加为通知“notif_foo”的观察者,但它可以选择仅通过将视图控制器A指定为对象参数来从视图控制器A接收“notif_foo”。
愚蠢的我没有意识到我的通知回调方法我可以去:
if([notification name] isEqualToString:@"notifName"])
{
...
}
else
{
...
}
希望这可以帮助那些正在解决这个问题的人。
答案 0 :(得分:0)
你可以在appdelegate中设置标志,告诉我们选择哪个控制器。然后发布该控制器的通知。请注意,如果有ui更改或类已发布,您需要在要发布通知的所有类中实现您的代码