2011-03-17 116 views
20

我的問題是關於被添加到-postNotificationName:object: userInfo:方法的對象。NSNotification是否保留該對象?

NSNotification是否保留該對象? (以類似的方式來的NSMutableDictionary或陣列)...這意味着張貼通知

下面後,我可以釋放的對象是一個代碼片段,幫助形容我的問題...是有效的釋放對象。鏈接到Apple文檔可能會非常有幫助。

NSMutableDictionary *teamDictCopy = [self.teamDict mutableCopy]; 
[teamDictCopy setObject:[NSNumber numberWithInt:self.scrollViewIndex] forKey:@"imageIndex"]; 

if([self.statusButton.title isEqualToString:@"Completed"]){ 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"UnComplete" object:teamDictCopy userInfo:nil]; 
} 

[teamDictCopy release]; 

回答

31

「是否NSNotification保留 對象?(以類似的方式來 的NSMutableDictionary或陣列)... 意思 後,我可以釋放對象張貼的通知」

我不確定objectuserInfo參數是否由該方法保留,但在實踐中,它應該沒有關係。

我想你可能會想象NSNotificationCenter正在創建這些通知並以異步方式廣播它們,但情況並非如此。至於NSNotificationCenter文檔中所述(見NSNotificationCenter Class Reference),通知同步發佈:

通知中心提供 通知觀察員 同步。換句話說, postNotification:方法不會 返回,直到所有觀察者有 收到並處理 通知。要發送通知 異步使用 NSNotificationQueue。在 多線程應用程序中, 通知總是在 中發佈,其中發佈通知 的線程可能與 本身已註冊的線程不同。

因此,在您的代碼中,通知中心創建通知,然後通過默認中心廣播它。任何已經註冊了通知名稱和對象組合的對象都會收到通知,然後執行他們在註冊通知時指定的選擇器。之後,控件返回發佈通知的類。

換句話說,當你的代碼到達[teamDictCopy release]行時,teamDictCopy已經被所有相關方「使用」了。所以,釋放它不應該有任何危險。

只是關於公約的說明。通常,參數object:是用於發佈通知的對象,userInfo:參數用於表示額外信息的NSDictionary。所以,通常情況下,你會處理通知如下:

NSMutableDictionary *teamDictCopy = [self.teamDict mutableCopy]; 
[teamDictCopy setObject: 
    [NSNumber numberWithInt:self.scrollViewIndex] forKey:@"imageIndex"]; 

if([self.statusButton.title isEqualToString:@"Completed"]){ 
[[NSNotificationCenter defaultCenter] postNotificationName:@"UnComplete" 
    object:self userInfo:teamDictCopy]; 
    } 

[teamDictCopy release]; 
+1

謝謝......你的回答比我提出的問題更清楚。 _always learning_ – MDMonty 2011-03-18 11:04:23

+5

如果NSNotifications僅與NSNotificationCenters一起使用,則情況會如此。關於NSNotificationQueue呢?在這種情況下,我們會異步發佈,並且無論對象是否保留,都無關緊要。 – DougW 2011-04-12 21:44:53

5

是的 - 你可以釋放對象,一旦它被設置爲通知的對象。

你也可以繼承子類。

至於特定的文件/聲明:我不記得一個,具體的。

然而,當類型被識別爲對象時,這是對象,它們的實例變量以及分佈式通信和信令的基礎。

我已經爲你寫了一個測試,所以你可以放心。如果對象未被保留,通知的用例將很少。只需在指示位置添加斷點,然後在啓用斷點的情況下運行。請享用!

#import <Foundation/Foundation.h> 

@interface MONObject : NSObject 
@end 

@implementation MONObject 

- (id)retain { 
    return self; /* << add breakpoint here */ 
} 

/* needed to counter retain override 
    (although all MONObjects will leak in this example) 
*/ 
- (void)release { 
} 

@end 

int main(int argc, const char* argv[]) { 
    NSAutoreleasePool * pool = [NSAutoreleasePool new]; 

    NSString * name = @"UnComplete"; 
    MONObject * obj = [MONObject new]; 
    [[NSNotificationCenter defaultCenter] postNotificationName:name object:obj userInfo:nil]; 
    [obj release], obj = 0; 

    [pool drain]; 
    return 0; 
} 
+0

嗨賈斯汀...能夠源的蘋果文件,以支持您的答案。我一直在尋找幾個小時,也許我錯過了它。 – MDMonty 2011-03-17 22:00:15

+0

@MDMonty我已經擴大了答案。你可以在'-MONObject版本]上添加一個斷點',如果你也想看看它的發佈點在哪裏執行。希望作爲確認。如果它是一個'void *',那麼絕對不要期望它被保留,但對象是'id'。 – justin 2011-03-17 23:09:19

+0

非常感謝。一個非常好的示範。我希望我能授予2'正確答案',因爲你的回答有助於恭維對方。 – MDMonty 2011-03-18 11:03:30

相關問題