2010-02-05 82 views
0

我對Objective-C非常陌生,我試圖開發一個iPhone應用程序。我的問題是當我在一個NSTimer中使用一個對象時,我得到了「消息發送到解除分配的實例0x3d54830」的錯誤。當我不使用NSTimer時,我可以很好地使用該對象。例如:Objective-C對象意外解除分配

//These can be any objects. Le't say I have a Song class and a SongReader class in the header file SongTest.h 
Song *song; 
SongReader *reader; 

NSTimer *timer; 

- (void)justDoIt; 


//In the implementation file SongTest.m 
- (void)viewDidLoad { 
    reader = [[SongReader alloc] init]; 
    song = [reader readSong]; 

    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(justDoIt) userInfo:nil repeats:YES]; 
} 

- (void)justDoIt { 
    NSLog(@"This is a song integer property: %d", song.wordCount); 
} 

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

的justDoIt方法/選擇/消息內的歌曲對象根據調試器已經釋放。我究竟做錯了什麼?即使我這樣做:

song = [[reader readSong] retain]; //or 
[song retain]; //or 
[reader retain]; 

該對象仍然意外地釋放分配。同樣,這個問題只發生在我使用NSTimer時。就像在計時器觸發之前對象被釋放一樣。

+0

順便說一句,請認爲沒有語法錯誤。問題是圍繞對象釋放(運行時)。這不是編譯器錯誤。 – tonex 2010-02-05 14:43:48

回答

1

你保留你的SongTest對象嗎?你不會顯示那部分代碼,但是如果它是自動發佈的,它將在計時器觸發時解除分配。事實上,這真的是錯誤消息表明:

「的消息發送到釋放實例0x3d54830」

要創建的計時器將消息發送到「自我」,這是SongTest目的。

此外,你需要保留歌曲:

song = [[reader readSong] retain]; 

如果你按照標準可可約定編碼-readSong。

+0

嘿,dodgio。我知道我說過「song = [[reader readSong] retain]」不適合我,但我在你這麼說之後再次嘗試過。現在,它的工作。另外,我明確釋放SongTest。我不必保留它。 謝謝,夥計! – tonex 2010-02-05 15:42:26

2

該問題可能是NSTimer調用的目標(即「自我」)。因此,消息「justDoIt」被髮送到解除分配的實例,代碼中的對象表示爲「self」。

控制器實例是否在定時器被觸發前解除分配?

+0

感謝您的回覆。控制器實例未取消分配。實際上,所有其他實例變量都可以在「justDoIt」消息中訪問。這只是我遇到問題的特定對象。 – tonex 2010-02-05 15:28:39

+0

嗨,肯。我非常感謝你的幫助。我找到了答案 - 請參閱dodgio的回覆。謝謝! – tonex 2010-02-05 15:44:54

0

您應該使用屬性來防止出現這類錯誤。如果你定義的歌曲作爲...

@property(nonatomic, retain) Song *song; 
... 
@synthesize song; 

...並使用它像這樣...

self.song = [讀者readSong]

... objective-c管理你的保留和釋放,直到你調用dealloc。

無關你的主要問題,由定時器叫應該是形式的方法...

-(void) arbitraryMethodName:(NSTimer *) aTimer; 

...或者它可能並不總是正確調用。

+0

你可能是對的TechZen。我不想使用屬性,因爲我認爲它更耗費資源。但現在我明白你的觀點。我也會試試這個。 – tonex 2010-02-06 16:24:34