Вы должны взглянуть на упаковщик fmdb на github. Даже если вы не используете его, посмотрите на код.
Где вы открываете базу данных? Вы закрываете это в этом коде. Прежде чем вы позвоните снова, он должен быть открыт. Вам следует подумать о том, чтобы оставить его открытым на время однопользовательского приложения iOS и закрыть, когда вы закончите. Что произойдет, если вы просто удалите закрытый вызов?
Первое, что вы должны сделать, это проверить все ваши коды возврата для вызовов sqlite. например, с шагом вы не обрабатываете ничего, кроме SQLITE_ROW. По крайней мере, войдите другие. Также для завершения и закрытия вы не обрабатываете и не регистрируете других.
Кроме того, вы готовите (компилируете) оператор sql, но не сохраняете его. prepare_v2 возвращает вам скомпилированное утверждение. Сохраните его как переменную-член и вызовите сброс для него, прежде чем использовать его снова.
Чтобы ответить на ваш конкретный вопрос о том, как закрыть - вы должны учитывать, что некоторые утверждения, возможно, не были завершены. Вот мой метод close: (Кстати, ENDebug - это моя оболочка над NSLog)
- (void)close
{
if (_sqlite3)
{
ENInfo(@"closing");
[self clearStatementCache];
int rc = sqlite3_close(_sqlite3);
ENDebug(@"close rc=%d", rc);
if (rc == SQLITE_BUSY)
{
ENError(@"SQLITE_BUSY: not all statements cleanly finalized");
sqlite3_stmt *stmt;
while ((stmt = sqlite3_next_stmt(_sqlite3, 0x00)) != 0)
{
ENDebug(@"finalizing stmt");
sqlite3_finalize(stmt);
}
rc = sqlite3_close(_sqlite3);
}
if (rc != SQLITE_OK)
{
ENError(@"close not OK. rc=%d", rc);
}
_sqlite3 = NULL;
}
}
наконец, рассмотрите возможность добавления гораздо большего количества журналов вместе с кодами возврата, чтобы вы могли получить больше информации.
Надеюсь, это поможет.