2013-05-17 78 views
2

我讀蘋果文檔,發現:IOS註銷觀察員

被觀察通知的對象被釋放之前, 必須告訴通知中心停止發送它的通知。 否則,下一個通知被髮送到一個不存在的對象,並且程序崩潰。

我試圖崩潰的應用程序,以更好地瞭解它是如何工作的。

但是,即使我沒有將此代碼放入SecondViewController dealloc中,它在發送通知後仍不會崩潰。我顯然添加了觀察者並從secondViewController返回並在viewController中推送通知。那麼,爲什麼我們需要刪除觀察者,如果這個程序沒有崩潰?

[[NSNotificationCenter defaultCenter] removeObserver:self];

休息代碼:

//視圖控制器:

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. } 

- (IBAction)go:(id)sender { 
    SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil]; 
    [self presentViewController:secondViewController animated:NO completion:^{}]; 
    [secondViewController release], secondViewController = nil; } 

- (IBAction)push:(id)sender { 
    // All instances of TestClass will be notified 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"TestNotification" object:self]; } 

// SecondViewController:

@implementation SecondViewController 

- (void)dealloc { 
    [super dealloc]; } 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     // Custom initialization 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(receiveTestNotification:) 
                name:@"TestNotification" 
                object:nil]; 

    } 
    return self; } 

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

- (void) receiveTestNotification:(NSNotification *) notification { 
    // [notification name] should always be @"TestNotification" 
    // unless you use this method for observation of other notifications 
    // as well. 
    NSLog (@"Successfully received the test notification!"); } 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. } 

- (IBAction)back:(id)sender { 
    NSLog(@""); 
    [self dismissViewControllerAnimated:NO completion:^{}]; } 
+1

刪除觀察者這樣 - [[NSNotificationCenter defaultCenter] removeObserver:@「TestNotification」];並通知像這樣 - [[NSNotificationCenter defaultCenter] postNotificationName:@「TestNotification」object:nil userInfo:nil]; –

+0

確定SecondViewController在通知被觸發之前被釋放了嗎? – thegrinner

+1

至於如果您未能移除觀察者就會崩潰,因此沒有*保證*您的應用在測試時會崩潰。但是當有人使用它時幾乎肯定會崩潰,並且很可能在Apple通過認證運行您的應用程序時。 –

回答

2

@Reno瓊斯是正確的。 刪除觀察者這樣的 - [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TestNotification" object:nil];

一件事添加到他的回答是,你應該刪除觀察者在- (void)dealloc {}方法 - 這是當自我被釋放時調用的方法。

編輯:

我已經看了代碼,我還沒有使用弧形看到。還有一個問題,你爲什麼不在你的應用程序中使用ARC?你有充分的理由來強調自己與參考計數,我沒有看到這一點?

其次,您可以在viewDidLoad方法中移動addObserver,並查看它崩潰了您的應用程序。

+2

這需要是'removeObserver:self'或'removeObserver:self name:@「TestNotification」object:nil' – Kevin

+1

@Kevin正確移除觀察者@「TestNotification」從觀察列表中移除靜態字符串對象...那不是我想你想要的。 –

+0

希望解決這個問題? –

0

dealloc方法SecondViewController未被調用,因爲對象仍在內存中,或者在控制器被釋放後不調用方法push:(id)sender。否則,它肯定會崩潰。確保通過放置斷點來調用方法。