代码之家  ›  专栏  ›  技术社区  ›  Sean

在目标C中为nsmutablearray对象使用指针

  •  0
  • Sean  · 技术社区  · 16 年前

    从Cocoa中的nsmutableArray中检索对象时,触摸下面的代码是否正常?我应该每次都分配([alloc])新的页面对象还是只指向它?我是否需要对后面的pageobj页做任何操作,例如将其设置为nil?

    const char *sql = "insert into Page(Book_ID, Page_Num, Page_Text) Values(?, ?, ?)";
    for (i = 0; i < ([[self pagesArray] count] - 1); i++) {
        if(addStmt == nil) {
            if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK) {
                NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));
            }
        }
        Page *pageObj = [[self pagesArray] objectAtIndex:i];
        if(pageObj.isNew) {
            sqlite3_bind_int(addStmt, 1, self.book_ID); 
            sqlite3_bind_int(addStmt, 2, pageObj.page_Number);  
            sqlite3_bind_text(addStmt, 3, [[pageObj page_Text] UTF8String], -1, SQLITE_TRANSIENT);
            if(SQLITE_DONE != sqlite3_step(addStmt)) {
                NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database));
            }
            NSLog(@"Inserted Page: %i into DB. Page text: %@", pageObj.page_Number, pageObj.page_Text);
        }
        //Reset the add statement.
        sqlite3_reset(addStmt);                     
    }
    

    谢谢。我也理解这可能是在一个交易中,但我还没有完全实现。

    3 回复  |  直到 13 年前
        1
  •  4
  •   Marc Charbonneau    16 年前

    声明指针的方式是正确的。您不需要alloc,因为当您想要引用数组中的现有对象时,它会创建一个新对象。如果要将引用保留在该方法之外,您可能希望保留它,但是由于您只是临时使用它,所以最好不要这样做。

    实际的指针变量将在每次循环的行程中被销毁并重新创建,因此不需要将其设置为nil。即使在循环之外声明了变量,也可以简单地将其分配给新对象。将其设置为nil的唯一时间是释放存储在指针中的对象(或者对象可能在其他地方释放)。如果在这种情况下没有将其设置为nil,指针将在对象解除锁定后引用无效的内存位置,通常会导致崩溃。

    不过,我看到的一个错误是,您将跳过for循环中数组中的最后一个元素,方法是从计数中减去1。

        2
  •  2
  •   Brad Larson    16 年前

    除了前面提到的计数错误之外,它看起来还不错。

    至于事务,我强烈建议将这个写循环包装成一个。它将大大提高您的写性能,我发现它也有助于内存的使用。我使用以下类方法开始事务:

    + (BOOL)beginTransactionWithDatabase:(sqlite3 *)database;
    {
        const char *sql1 = "BEGIN EXCLUSIVE TRANSACTION";
        sqlite3_stmt *begin_statement;
        if (sqlite3_prepare_v2(database, sql1, -1, &begin_statement, NULL) != SQLITE_OK)
        {
            return NO;
        }
        if (sqlite3_step(begin_statement) != SQLITE_DONE) 
        {
            return NO;
        }
        sqlite3_finalize(begin_statement);
        return YES;
    }
    

    而这一次是为了结束交易:

    + (BOOL)endTransactionWithDatabase:(sqlite3 *)database;
    {
        const char *sql2 = "COMMIT TRANSACTION";
        sqlite3_stmt *commit_statement;
        if (sqlite3_prepare_v2(database, sql2, -1, &commit_statement, NULL) != SQLITE_OK)
        {
            return NO;
        }
        if (sqlite3_step(commit_statement) != SQLITE_DONE) 
        {
            return NO;
        }
        sqlite3_finalize(commit_statement);
        return YES;
    }
    

    我可能应该存储SQL语句以备日后重用,但这些事务语句的调用频率比其他查询要低得多。

        3
  •  1
  •   Mehrdad Afshari    16 年前

    当然不是。您以前已经分配过它,现在只是引用同一个对象。不需要重新分配。你也不需要把它设为零。