简体   繁体   English

在Objective C中为NSMutableArray对象使用指针

[英]Using pointers in Objective C for NSMutableArray objects

When retrieving objects from an NSMutableArray in cocoa-touch is the below code ok? 在可可触摸中从NSMutableArray检索对象时,以下代码可以吗? Should I be allocating([alloc]) new Page objects each time or is just pointing to it alright? 我应该每次分配([alloc])新的Page对象,还是只是指向它? Do I need to do anything to the Page *pageObj after, such as set it to nil? 之后,是否需要对Page * 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);                     
}

Thanks. 谢谢。 I also understand this should probably be in a transaction but I didn't quite get that working just yet. 我也知道这可能应该在交易中,但我还没有完全解决这个问题。

The way you're declaring a pointer is correct. 您声明指针的方式是正确的。 You don't need alloc, since that creates a new object, when you want to refer to an existing object in the array. 当您要引用数组中的现有对象时,不需要alloc,因为这会创建一个新对象。 You would want to retain it if you were going to keep the reference outside of that method, but since you're only using it temporarily it's fine not to. 如果要将引用保留在该方法之外,则希望保留它,但是由于您只是临时使用它,所以最好不要使用它。

The actual pointer variable will be destroyed and recreated every trip to the loop, so there's no need to set it to nil. 实际的指针变量将在每次循环时被销毁并重新创建,因此无需将其设置为nil。 Even if you declared the variable outside the loop, simply assigning it to a new object is fine. 即使您在循环外声明了变量,只需将其分配给新对象也可以。 The only time you'd set it to nil is when you're releasing the object stored in the pointer (or the object may be released elsewhere). 唯一将其设置为nil的情况是释放存储在指针中的对象(或者该对象可能在其他地方释放)。 If you didn't set it to nil in that case, the pointer would refer to an invalid memory location after the object is dealloced, usually causing a crash. 如果在这种情况下未将其设置为nil,则指针在分配对象后将指向无效的内存位置,通常会导致崩溃。

One bug I can see though, you're skipping the last element in your array in your for loop by subtracting 1 from the count. 我可以看到一个错误,您通过从计数中减去1来跳过for循环中数组中的最后一个元素。

Aside from the previously mentioned count error, it looks good. 除了前面提到的计数错误外,它看起来还不错。

As far as transactions go, I highly recommend wrapping this write loop in one. 就事务而言,我强烈建议将此写循环包装为一个。 It will greatly increase your write performance and I found that it helps with memory usage as well. 这将大大提高您的写入性能,我发现它也有助于内存使用。 I use the following class method to begin a transaction: 我使用以下类方法开始事务:

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

and this one to end a transaction: 而这个结束交易:

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

I should probably store the SQL statements for later reuse, but these transaction statements are called much less frequently than my other queries. 我可能应该存储SQL语句以供以后重用,但是与我的其他查询相比,这些事务语句的调用频率要低得多。

Of course not. 当然不是。 You have allocated it before and are just referencing the same object. 您之前已经分配了它,只是在引用同一对象。 No need to reallocate. 无需重新分配。 Also you don't need to set it to nil. 另外,您无需将其设置为nil。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM