2011-11-11 55 views
0

我有一個NSDate *那我存儲爲與保留關鍵字屬性:爲什麼我需要保留NSDateFormatter dateFromString結果:

@property (nonatomic, retain) NSDate* startTime;

我用它如下:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
[dateFormatter setDateFormat:@"h:mm a"]; 
startTime = (NSDate*)[[NSUserDefaults] standardUserDefaults] objectForKey:@"StartTimeKey"]; 
if (startTime == nil) 
    startTime = [[dateFormatter dateFromString:@"8:00 am"] retain]; 

爲什麼我需要保留dateFromString:消息的結果,但我不需要保留objectForKey:的結果?

我剛剛升級到XCode 4.2,現在我正在使用LLVM GCC 4.2編譯器。升級之前,代碼工作正常,沒有保留。現在它在沒有保留消息的情況下崩潰(稍後在代碼中訪問startDate屬性時)。

+0

按規則,你不應該保留它,因爲dateFromString會自動釋放,但startTime屬性應保留在賦值,因爲它歸因於保留 – bryanmac

+0

順便說一句,看起來像dataFormatter泄漏(如果你不使用ARC)。 –

+0

@DavidDunham - 我認爲這是standardUserDefaults objectForKey:泄漏。 – LandedGently

回答

4

的問題是,你寫這樣的:

​​

你直接設置實例變量startTime。如果你這樣做,而不是:

self.startTime = blah blah blah; 

那麼編譯器會把它變成這樣:

[self setStartTime:blah blah blah]; 

,並自動生成setter方法將做保留你。

如果你這樣做:

@synthesize startTime = _startTime; 

則實例變量將被命名爲_startTime,使其更容易記住使用,而不是直接分配給實例變量的財產。

+1

+1 - 順便說一下,這就是爲什麼我喜歡用iVar的_startTime之類的東西來區分iVar和屬性。那麼當你直接進入iVar的時候就非常清楚了。 – bryanmac

+0

@rob - 感謝您的澄清。我正在做錯誤的假設,即'startTime'是'self.startTime'的同義詞和快捷鍵現在我看到它們確實引用了同一個對象,但是當使用'self.startTime'訪問屬性時,XCode會添加魔法隱藏代碼來執行保留。 – LandedGently

+0

仍然不清楚爲什麼standardUserDefaults objectForKey:似乎在上面的代碼中添加了額外的保留計數。 – LandedGently

1

答案是內存管理編程指南第11頁

你自己創建一個對象(即你不需要把它保留下來,已完成)。你用alloc,new,copy或mutablecopy創建一個對象。在這種情況下,dateFormatter爲您提供了一個新的對象,但由於您沒有調用alloc,new或copy自己,所以dateFormatter會在新的NSDAte對象上調用(通常是它的工作方式)autorealease。

但是,如果你使用setter和getter設置你的屬性,你就不會有這個問題。

+0

感謝您的回答。正如我在@ rob的回答中對我的評論中所提到的那樣,我認爲我正在設置這個屬性,並沒有意識到我實際上給了iVar一個值,因此繞過了setter。 – LandedGently

相關問題