我在我的应用程序中使用以下函数:
+(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类的Object。
在我分配对象的代码中: objOpponentTTL = [[TeamTournamentLookUp alloc] initWithPrimaryKey:primaryKey];
现在我的问题是我应该在哪里发布该对象?
答案 0 :(得分:4)
如果您正在为Objective C 2编写代码,那么您不需要使用垃圾回收构建更多代码。如果对于包括iPhone在内的早期版本,则需要在某个阶段发布它。
在这种情况下,通常的方法是在创建它时自动释放它。 e.g。
objOpponentTTL = [[[TeamTournamentLookUp alloc] initWithPrimaryKey:primaryKey]autorelease];
当您到达自动释放池时,将释放该对象。默认情况下,NSApplication中有一个这样,并在输入循环中调用。
有关内存管理的更多信息,请阅读Apple's docs on memory management
答案 1 :(得分:1)
在退回之前发送autoRelease
消息。这样它就会收到发送给它的发布消息,但不仅仅是。
然后无论调用你的方法,都必须retain
返回的对象。
您可以在Apple文档中查找处理retain,release,autoRelease的模式。学习一些基本规则非常方便。
答案 2 :(得分:1)
使用objective-c,从技术上讲,你的函数应该自动释放你返回的对象,例如
return [autorelease objOpponentTTL];
调用对象应该保留返回的对象,例如
TeamTournamentLookUp * object = [[self getOpponentTeamTournamentLookUp:5:6] retain];
当你使用'object'时,你应该释放它,即。
[object release]
我还没有真正使用过Objective-C 2.0及其垃圾收集,所以如果打开垃圾收集,我不确定语法应该是什么。但是,如果您使用的是标准Objective-C,那么这对您来说应该没问题。
没有垃圾收集,惯例是在你想要使用它时保留一个对象,并在你完成它时释放它。如果你要将'object'添加到容器(例如NSMutableArray),你正在调用的函数将保留该对象,并且你可以在添加到集合后安全地释放它,例如。
....
TeamTournamentLookUp * object = [[self getOpponentTeamTournamentLookUp:5:6] retain];
[my_lookup addObject:object];
[object release];
....
希望这有帮助!
答案 3 :(得分:1)
除了其他答案之外,我还会看一下您的设计和命名约定,以便让您的对象管理更加清晰。 Apple在其API上使用约定,这使得调用者有责任释放返回的对象以及在其他地方管理对象的生命周期时非常清楚。
对于初学者,您的方法名称以“get”开头。这对我来说意味着它返回的对象有自己的生命周期,与我的调用方法无关,我根本不应该释放它!
当调用以'make'或'create'开头的方法时,那告诉我已经为我创建了返回的对象,并且当我完成它时我有责任释放它。
注意 :我应该注意这是从iPhone开发的角度编写的,整体上并不大> autorelease 的事情......
答案 4 :(得分:1)
这种形式的类方法用于分配和初始化对象。但是,您已在其声明中将objOpponentTTL
设置为nil,并且从不分配它,但您确实在说明中提到了所需的分配行。如果包含该行,则此功能基本上可以。虽然(正如ed提到的)它被称为getXXX
这一事实违反惯例;像这样的类方法应该以它创建并返回的对象类型命名。
关于何时释放它的问题,这完全取决于其生命周期和拥有对象的范围。简短的回答是:当你不再需要它时!
例如,如果此对象是与团队关联的特殊数据且团队属于游戏,那么您将在游戏的dealloc方法中释放它。游戏可能会由控制器创建和发布。
其他人提到自动释放,但这可能不是你想要的。当你有一个想要从方法返回的瞬态对象时,这很有用,但你将不再拥有它的句柄(返回NSString
就是一个很好的例子)。这看起来像是一组更大的对象的一部分。
您确实需要考虑应用程序的设计以及对象的交互方式。绘制一些序列图,并查看所需的信息,时间和对象。上面的例子(控制器拥有一个拥有玩家的游戏)是一个相当普遍的起点。
对象的范围(以及声明它的位置)会告诉你很多东西。例如,如果对象是数据成员,您通常会在init
或awakeFromNib
方法中分配它,并在dealloc
方法中释放它。如果它是工厂方法(例如您的示例),您将创建它并且(按照惯例)调用者有责任释放它。如果它是一个创建一次性对象的访问器,你可能会使用autorelease。
正如其他人所指出的,关于内存管理的Apple文档非常好。关于如何安全地管理内存有非常明确的约定,因此值得在他们自己的代码中按照这些约定进行调整。