我有下一个代码:
@implementation SplashViewVC
- (void)viewDidLoad
{
[super viewDidLoad];
self.splashView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Default.png"]];
self.activityIndicator.originY = 355.f;
[[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){
NSInteger errorCode = [n.userInfo[@"errorCode"] integerValue];
[self.activityIndicator stopAnimating];
if (errorCode == ERROR_CODE_NO_CONNECTION) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Some problem with server" delegate:self cancelButtonTitle:@"try again" otherButtonTitles:nil];
[alertView show];
} else if (errorCode == 0) {
[self dismissViewControllerAnimated:YES completion:nil];
}
}];
[self downloadData];
}
- (void)downloadData
{
[self.activityIndicator startAnimating];
[[Server sharedServer] getMovieData];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[self downloadData];
}
- (void)viewDidDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super viewDidDisappear:animated];
}
@end
所以我在viewDidLoad
方法的viewDidDisappear
方法的开头放置了断点。当我启动首先转到viewDidload
的应用时,下载后转到viewDidDisappear
。
但在我的应用中,我再次下载数据并发布notification: NSDownloadComplete
。在这个VC中它是有效的,但我后来使用:
[[NSNotificationCenter defaultCenter] removeObserver:self]
此VC在开始时使用viewDidLoad
一次&不能再添加Observer。
有什么问题?
修改
我尝试将addObserver方法添加到viewWillAppear
或viewWillDisappear
- 没有结果。
我在
NSLog(@"addObserver");
[[NSNotificationCenter defaultCenter] addObserverForName...
在viewDidLoad
中并写
- (void)viewDidDisappear:(BOOL)animated
{
NSLog(@"removeObserver");
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super viewDidDisappear:animated];
}
在日志中我看到:
2013-06-10 14:32:05.646 myApp[9390:c07] addObserver
2013-06-10 14:32:06.780 myApp[9390:c07] removeObserver
有什么不对?
编辑2 您可以看到必须删除观察者,但它在addObserver方法
中再次运行块
答案 0 :(得分:24)
除了添加/删除观察者调用未正确平衡之外,在其他答案中还有另外一个问题。
删除观察者的代码是错误的。对于基于块的观察者,addObserver
的返回值必须作为removeObserver
的参数给出。所以你应该添加一个属性
@property(nonatomic, strong) id observer;
上课。然后用
添加观察者self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){
// ...
}];
并使用
将其删除[[NSNotificationCenter defaultCenter] removeObserver:self.observer];
答案 1 :(得分:5)
e1985试图揭露的是addObserver
和removeObserver
来电未正确平衡。 VC初始化后只调用viewDidLoad
一次,但每次将视图控制器移出屏幕时都会调用viewDidDisappear
。
要解决您的问题,您必须平衡addObserver
和removeObserver
来电,方法是将它们放在viewDidLoad
中,将另一个放在dealloc
中,或者 - 如e1985建议的那样 - 在viewDidAppear:
和viewDidDisappear:
。
编辑:好的,所以问题来自于您使用的addObserverForName:object:queue:usingBlock:
没有注册self
作为观察者(因为addObserver:selector:name:object:
会这样做如果你传递self
作为第一个参数。)
因此,在您的情况下,[[NSNotificationCenter defaultCenter] removeObserver:self];
不执行任何操作,因为self
不是观察者。您应该在removeObserver:
的返回值上调用addObserverForName:object:queue:usingBlock:
,如图in the doc所示:
返回值
一个不透明的对象充当观察者。
所以你的代码看起来应该是这样的:
// header file .h
@interface SplashViewVC : UIViewController
@property (strong, nonatomic) id downloadCompleteObserver;
@end
// implementation file .m
@implementation SplashViewVC
- (void)viewDidLoad
{
[super viewDidLoad];
// [...] snip
self.downloadCompleteObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){
NSInteger errorCode = [n.userInfo[@"errorCode"] integerValue];
[self.activityIndicator stopAnimating];
if (errorCode == ERROR_CODE_NO_CONNECTION) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Some problem with server" delegate:self cancelButtonTitle:@"try again" otherButtonTitles:nil];
[alertView show];
} else if (errorCode == 0) {
[self dismissViewControllerAnimated:YES completion:nil];
}
}];
[self downloadData];
}
// [...] snip
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self.downloadCompleteObserver];
[super dealloc];
}
@end
答案 2 :(得分:3)
您使用的模式不正确。您应该在viewDidAppear:
中添加观察者并将其移除viewDidDisappear:
。