2012-04-10 36 views
2

我創建了DownloadAndParseBook類。在它收到任何數據或網絡錯誤之前,它不會自動重新排列。使用[自我釋放],[自我保留]是好方法嗎?

我用[自我釋放],[自我保留]。使用[自我釋放],[自我保留]是好方法嗎? DownloadAndParseBook是否包含任何潛在的錯誤?

@implementation GetBooks 

-(void) books 
{ 
for(int i =0; i<10; i++) 
{ 
    DownloadAndParseBook *downloadAndParseBook = 
     [[[DownloadAndParseBook alloc] init]autorelease]; 
    [downloadAndParseBook startLoadingBook]; 
} 
} 
@end 


@implementation DownloadAndParseBook 

- (id)initWithAbook:(int)bookID 
{ 
if(self = [super init]) 
{ 
    [self retain];   
} 
return self; 
} 

- (void)startLoadingBook 
{ 
[NSURLConnection connectionWithRequest:request delegate:self]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    [self release];  
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
[self saveResultToDatabase]; 
[self release]; 
} 


@end 
+1

如果可以幫助,不要使用'[self release]'。 – Manuel 2012-04-10 12:56:31

+0

是的,'[自我釋放]'是一個等待發生的崩潰。從父母釋放。 – 2012-04-10 13:34:59

回答

2

自我保留非常偶爾是一種合適的模式。這很少見,但有時在某些類型的多線程代碼中,確保在處理某些內容時不會消失很重要。這就是說,這不是其中之一。我很難想象一個你目前的方法會有所幫助的情況。如果有人創建了你的對象,然後再也不會調用startLoadingBook,那麼它就會泄漏。如果有人撥打startLoadingBook,則無論如何都會保留您的對象,因爲NSURLConnection會保留其委託直至完成。

這就是說,我相信你的問題很大程度上來自於你的對象模型是錯誤的。 GetBooksDownloadAndParseBook都不適合作爲類。你可能的意思是BookManager(東西來容納所有的書)和BookDownloadController(管理下載一本書的東西)。 BookManager應跟蹤所有當前BookDownloadControllers(在NSSetNSArray伊娃)。每個BookDownloadController應該跟蹤它的NSURLConnection(以ivar)。你不應該只是建立聯繫,讓他們「自己掛」(即自我保留)。這感覺很方便,但它使代碼很難處理。您無法控制您正在創建的連接數量。您無法取消連接。它變得非常迅速混亂。

+0

謝謝。我不想違反任何好的模式,所以我需要改變我的對象模型。你是對的。 – Voloda2 2012-04-10 15:00:26

0

問題是:爲什麼一個對象需要保留自己?您可能想要像單身人士一樣實施您的課程。

+0

你可能要發表評論作爲評論,而不是答案 – MrTJ 2012-04-10 13:28:11

1

不,這不是最佳做法。 保留/釋放你的物體應該由物體的「所有者」完成。 對於您的特定示例,您的DownloadAndParseBook對象的所有者是執行alloc/init的對象。這應該是保留/釋放您的DownloadAndParseBook實例。 這裏的最佳實踐是DownloadAndParseBook的alloc/init,保留由所有者完成,所有的下載/解析邏輯,然後向所有者發送回調,以完成所有操作(例如通過委託),在此時, ower向你的對象發送釋放消息。

0

與其他響應者不同,我會說你的模式可能工作。另請參見Is calling [self release] allowed to control object lifetime?

有然而,在你的代碼中的一些其他問題:

  • -(void) books我猜你想發送的startLoadingBook消息downloadAndParseBook,而不是self
  • 如果創建一個initWithAbook方法,它在您使用標準init方法初始化您的書時不會被調用。在上述[self retain]當前的代碼將永遠不會被調用
  • 在你上面的代碼bookID不會
  • 我不會用「初始化」模式在這裏保存,但一切都在一個靜態函數因此主叫方無法利用的錯誤與班級所有權。

代碼:

- (id) initWithId:(int)bookId { 
    self = [super init]; 
    if (self) { 
    // save bookId here 
    } 
    return self; 
} 

+ (void) startLoadingBookWithID:(int)bookId { 
    DownloadAndParseBook* book = [[DownloadAndParseBook alloc] initWithId:bookId]; 
    [NSURLConnection connectionWithRequest:request delegate:book]; 
} 

// release self when it finished the operation 
// and document well that its behaviour 

如果你想好,NSURLConnection本身應該工作完全相同的方式:當你不釋放NSURLConnection當它完成其工作,但它本身它。但是,在connectionWithRequest中,它也不能自動釋放,因爲它必須處於活動狀態,直到請求被提供。所以它可以工作的唯一方法是上述模式

+0

我希望從downvoter評論。 – MrTJ 2012-04-10 15:08:23

+0

我就是這樣。當我的連接委託被調用並且一切都已完成時,我調用[self release],否則你需要在你要求啓動連接的地方保留一個指向你的其他類的指針,並且它很重。但即時通訊只是想你真的可以發送自己的代表誰可以釋放它 – 2012-05-29 15:19:53

0

永遠不要使用[self release]。唯一可能的例外是單例類/對象。方法releaseretain應該只由對象的所有者發送。這通常意味着無論哪個對象創建了該對象,也應該是釋放該對象的對象。

相關問題