2009-12-03 65 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。

正如其他人所指出的,苹果有关内存管理的文档非常好。关于如何安全地管理内存有非常明确的约定,所以值得对它们进行修改,并遵循这些约定在您自己的代码中。