【问题标题】:Objective-C + release ObjectsObjective-C + 释放对象
【发布时间】:2010-12-22 18:30:14
【问题描述】:

我在我的应用程序中使用以下函数:

+(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];

现在我的问题是我应该在哪里释放对象?

【问题讨论】:

    标签: objective-c object release


    【解决方案1】:

    如果您正在为 Objective C 2 编写代码,那么您无需编写更多代码,只需使用垃圾收集构建即可。如果对于包括 iPhone 在内的早期版本,则需要在某个阶段发布它。

    在这种情况下,通常的方法是在创建它时自动释放它。例如

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

    当您到达自动释放池时,该对象将被释放。在 NSApplication 中默认有其中之一,并在输入循环中被调用。

    有关内存管理的更多信息,请阅读Apple's docs on memory management

    【讨论】:

      【解决方案2】:

      在您退回之前发送autoRelease 消息。这样它就会收到一条发布消息,但还不是现在。

      那么无论调用你的方法,都必须retain返回的对象。

      您可以在 Apple 文档中查找处理保留、释放、自动释放的模式。学习一些基本规则非常方便。

      【讨论】:

        【解决方案3】:

        使用objective-c,从技术上讲,您的函数应该自动释放您返回的对象,例如。

        return [autorelease objOpponentTTL];
        

        调用对象应保留返回的对象,例如。

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

        当你用完'object'后,你应该释放它然后ie。

        [object release]
        

        我还没有真正使用过 Objective-C 2.0 及其垃圾收集,所以我不确定如果你打开了垃圾收集应该是什么语法。但是,如果您使用的是标准 Objective-C,那么这对您来说应该没问题。

        如果没有垃圾回收,约定是在你想使用一个对象时保留它,并在你用完它时释放它。如果您要将“对象”添加到容器(例如 NSMutableArray),您调用的函数将保留该对象,并且您可以在添加到集合后安全地释放它,例如。

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

        希望这会有所帮助!

        【讨论】:

          【解决方案4】:

          除了其他答案之外,我会查看您的设计和命名约定,以使您的对象管理更加清晰。 Apple 在其 API 中使用了一个约定,当调用者有责任释放返回的对象以及对象的生命周期何时在其他地方进行管理时,这一约定非常明确。

          阅读Apple's guidlines

          对于初学者,方法的名称以“get”开头。这对我来说意味着它正在返回一个对象,它有自己的生命周期,独立于我的调用方法,我根本不应该释放它!

          当调用以“make”或“create”开头的方法时,这会告诉我返回的对象已为我创建,我有责任在完成后释放它。

          注意:我要注意的是,这是从 iPhone 开发的角​​度写的,在整个 autorelease 事情上并不重要...

          【讨论】:

          • 我可能错了,但你不想要 d=[[NSData alloc] init];那么您将需要在以后进行 [d 发布]。我的理解是 alloc 为一个对象分配内存,并以 1 的保留计数返回它。基本上它不会去任何地方,直到你释放(你负责)。
          • -1, [[NSDate alloc] retain]; 导致保留计数为 2 而不是 1,因为 alloc 已将保留计数设置为 1(如提及的模糊山羊)。
          【解决方案5】:

          这种形式的类方法用于分配和初始化一个对象。但是,您在其声明中将 objOpponentTTL 设置为 nil 并且从未分配它,尽管您确实在描述中提到了所需的分配行。如果包括那行,这个功能基本上就可以了。尽管(正如 ed 提到的)它被称为 getXXX 的事实是违反惯例的;像这样的类方法应该以其创建和返回的对象类型命名。

          至于何时释放它,这完全取决于它的生命周期和拥有对象的范围。简短的回答是:当您不再需要它时!

          例如,如果此对象是与团队相关的特殊数据,并且该团队属于游戏,那么您将在游戏的 dealloc 方法中释放它。并且游戏可能会由控制器创建和发布。

          其他人提到了自动释放,但这可能不是您想要的。当您有一个要从方法返回的瞬态对象时,这很有用,但您将不再拥有它的句柄(返回 NSString 是一个很好的例子)。这看起来像是一组更大对象的一部分。

          您确实需要考虑应用程序的设计以及对象如何交互。画一些序列图,看看需要什么信息,什么时候,什么对象。上面的例子(控制器拥有一个拥有玩家的游戏)是一个相当通用的起点。

          对象的范围(以及它的声明位置)告诉您很多信息。例如,如果一个对象是一个数据成员,您通常会在initawakeFromNib 方法中分配它,并在dealloc 方法中释放它。如果它是工厂方法(例如您的示例),您将创建它并且(按照惯例)释放它是调用者的责任。如果它是一个创建一次性对象的访问器,您可能会使用自动释放。

          正如其他人所指出的,Apple 关于内存管理的文档非常好。关于如何安全地管理内存有非常明确的约定,因此值得深入了解它们并在您自己的代码中遵循这些约定。

          【讨论】:

            猜你喜欢
            • 2011-10-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多