2009-12-03 66 views
2

我使用下面的函數在我的應用程序:的Objective-C +發行對象

+(TeamTournamentLookUp *)getOpponentTeamTournamentLookUp:(int)tournamentId:(int)opponentTeamId 
{ 
    TeamTournamentLookUp *objOpponentTTL = nil; 
    const char *sql = "SELECT TeamTournamentLookUpID, TournamentID, TeamID, NumberOfWins, NumberOfLosses, NumberOfDraws, Points, Rank, IsUserTeam from TeamTournamentLookUp where TournamentID = ? and TeamID = ?"; 
    sqlite3_stmt *selectstmt; 
    if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) != SQLITE_OK) 
    NSAssert1(0, @"Error. '%s'", sqlite3_errmsg(database)); 

    sqlite3_bind_int(selectstmt, 1, tournamentId); 
    sqlite3_bind_int(selectstmt, 2, opponentTeamId); 

    if(SQLITE_DONE != sqlite3_step(selectstmt)) 
    { 
     NSInteger primaryKey = sqlite3_column_int(selectstmt, 0); 
     objOpponentTTL = [[TeamTournamentLookUp alloc] initWithPrimaryKey:primaryKey]; 
     objOpponentTTL.tournamentId = sqlite3_column_int(selectstmt, 1); 
     objOpponentTTL.teamId = sqlite3_column_int(selectstmt, 2); 
     objOpponentTTL.numberOfWins = (sqlite3_column_type(selectstmt, 3) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 3); 
     objOpponentTTL.numberOfLosses = (sqlite3_column_type(selectstmt, 4) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 4); 
     objOpponentTTL.numberOfDraws = (sqlite3_column_type(selectstmt, 5) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 5); 
     objOpponentTTL.points = (sqlite3_column_type(selectstmt, 6) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 6); 
     objOpponentTTL.rank = (sqlite3_column_type(selectstmt, 7) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 7); 
     objOpponentTTL.isUserTeam = (sqlite3_column_type(selectstmt, 9) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 9); 
    } 

    return objOpponentTTL; 
} 

基本上我回國TeamTournamentLookUp類的對象。

在代碼中我分配的對象: objOpponentTTL = [[TeamTournamentLookUp alloc] initWithPrimaryKey:primaryKey];

現在我的問題是我應該在哪裏發佈該對象?

回答

4

如果您正在編寫Objective C 2,那麼您不需要使用垃圾回收來構建更多的代碼。如果對於包括iPhone在內的早期版本,則需要在某個階段釋放它。

在這種情況下,通常的方法是在創建它時自動釋放它。例如

objOpponentTTL = [[[TeamTournamentLookUp alloc] initWithPrimaryKey:primaryKey]autorelease]; 

該對象將在您到達autorelease池時被釋放。 NSApplication中有一個默認值,並在輸入循環中被調用。

更多關於內存管理閱讀Apple's docs on memory management

1

發送它的autoRelease消息返回之前。這樣它會得到一個釋放消息發送給它,但不只是。

然後無論調用你的方法將不得不retain返回的對象。

您可以在Apple文檔中查找處理retain,release,autoRelease的模式。學習一些基本規則非常方便。

1

使用objective-c,在技術上你的函數應該autorelease你返回的對象,例如。

return [autorelease objOpponentTTL]; 

調用對象應該保留返回的對象,例如:

TeamTournamentLookUp * object = [[self getOpponentTeamTournamentLookUp:5:6] retain]; 

當你完成使用'對象',你應該釋放它然後ie。

[object release] 

我還沒有真正使用的Objective-C 2.0和垃圾收集,所以我不知道語法應該是什麼,如果你有垃圾收集打開。但是,如果你使用標準的Objective-C,那麼這對你應該沒問題。

沒有垃圾回收,約定是當你想使用它的時候保留一個對象,當你完成它時釋放它。如果您要將「對象」添加到容器(例如,NSMutableArray),那麼您調用的函數將保留該對象,並且可以在添加到集合後安全地釋放它,例如。

.... 
TeamTournamentLookUp * object = [[self getOpponentTeamTournamentLookUp:5:6] retain]; 
[my_lookup addObject:object]; 
[object release]; 
.... 

希望這有助於!

1

除了其他的答案,我會看看你的設計和命名約定,讓你的對象管理更清晰。蘋果公司在他們的API上使用了一個慣例,這使得調用者有責任釋放一個返回的對象,並且該對象的生命週期在其他地方被管理時這一點非常清楚。

請仔細閱讀Apple's guidlines

對於初學者,您的方法名稱以'get'開頭。這意味着它會返回一個擁有自己的生命週期的對象,而且與我的調用方法無關,我不應該釋放它!

當調用以'make'或'create'開頭的方法時,那告訴我返回的對象是爲我創建的,我有責任在我完成時釋放它。

我要指出,這是從iPhone的發展,這是不是對整個自動釋放事大的角度寫的...

+0

我可能是錯的,但你不想要d = [[NSData alloc] init];那麼你需要在以後做一個[d版本]。這是我的理解alloc爲一個對象分配內存,並返回它與保留計數爲1.基本上它不會去任何地方,直到你做一個釋放(你負責)。 – fuzzygoat 2009-12-03 19:22:54

+0

-1,'[[NSDate alloc] retain];'導致保留計數爲2而不是1,因爲alloc已經將保留計數設置爲1(如提到的模糊)。 – 2011-08-29 09:51:27

1

使用類方法的這種形式分配和初始化一個對象。但是,您已將objOpponentTTL設置爲在其聲明中爲零,並且從不分配它,儘管您在描述中提及了必需的分配行。如果包含這一行,這個函數基本上可以。雖然(正如編者所言)它被稱爲getXXX的事實違反了慣例;像這樣的類方法應該根據它創建並返回的對象類型命名。

至於何時發佈它的問題,完全取決於它的生命週期和擁有對象的範圍。簡短的回答是:當你不再需要它時!

例如,如果此對象是與團隊相關的特殊數據,並且團隊屬於某個遊戲,那麼您可以使用遊戲的dealloc方法釋放它。遊戲可能會由控制器創建併發布。

其他人提到autorelease,但這可能不是你想要的。當你想從方法中返回一個瞬態對象時,這很有用,但是你將不再有一個句柄(返回NSString就是一個很好的例子)。這看起來像是一組更大的對象的一部分。

您確實需要考慮應用程序的設計以及對象如何交互。繪製一些序列圖,並查看需要什麼信息,什麼時候以及什麼對象。上面的例子(控制器擁有一個擁有玩家的遊戲)是一個相當通用的起點。

對象的範圍(以及它聲明的地方)告訴你很多。例如,如果某個對象是數據成員,則通常將其分配到initawakeFromNib方法中,然後在dealloc方法中將其釋放。如果它是一個工廠方法(比如你的例子),你可以創建它並且(按照慣例),調用者有責任釋放它。如果它是一個創建一次性對象的訪問器,那麼你可能會使用autorelease。

正如其他人所指出的,蘋果有關內存管理的文檔非常好。關於如何安全地管理內存有非常明確的約定,所以值得對它們進行修改,並遵循這些約定在您自己的代碼中。