Использование указателей в Objective C для объектов NSMutableArray - PullRequest
0 голосов
/ 09 января 2009

При извлечении объектов из NSMutableArray в режиме cocoa-touch приведенный ниже код подходит? Должен ли я каждый раз выделять ([alloc]) новые объекты Page или просто указывает на это нормально? Нужно ли мне что-либо делать с 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);                     
}

Спасибо. Я также понимаю, что это, вероятно, должно быть в транзакции, но я еще не совсем понял, что это работает.

Ответы [ 3 ]

4 голосов
/ 09 января 2009

То, как вы объявляете указатель, является правильным. Вы не нуждаетесь в alloc, поскольку это создает новый объект, когда вы хотите сослаться на существующий объект в массиве. Возможно, вы захотите сохранить его, если собираетесь сохранить ссылку за пределами этого метода, но поскольку вы используете ее только временно, не стоит этого делать.

Фактическая переменная-указатель будет уничтожаться и пересоздываться при каждой поездке в цикле, поэтому нет необходимости устанавливать ее в ноль. Даже если вы объявили переменную вне цикла, просто назначьте ее новому объекту. Единственный раз, когда вы устанавливаете его на ноль, это когда вы освобождаете объект, сохраненный в указателе (или объект может быть освобожден в другом месте). Если в этом случае вы не установили значение nil, указатель будет указывать на недопустимое расположение в памяти после освобождения объекта, что обычно вызывает сбой.

Одна ошибка, которую я вижу, вы пропускаете последний элемент в вашем массиве в цикле for, вычитая 1 из числа.

2 голосов
/ 10 января 2009

Помимо ранее упомянутой ошибки подсчета, выглядит хорошо.

Что касается транзакций, я настоятельно рекомендую обернуть этот цикл записи в один. Это значительно повысит вашу производительность записи, и я обнаружил, что это также помогает с использованием памяти. Я использую следующий метод класса для начала транзакции:

+ (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 для последующего повторного использования, но эти операторы транзакций вызываются гораздо реже, чем мои другие запросы.

1 голос
/ 09 января 2009

Конечно нет. Вы разместили его раньше и просто ссылаетесь на один и тот же объект. Нет необходимости перераспределять. Также вам не нужно устанавливать его на ноль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...