Прежде всего, я читал много вопросов, которые кажутся похожими на мои, и даже получил несколько советов от нескольких, чтобы достигнуть точки, где я нахожусь, поэтому я благодарю вас, пользователи stackoverflow.
Хорошо, у меня есть пять таблиц базы данных в SQLite для iOS-приложения и их эквивалент в MySQL для удаленного сервера. Данные, которые я предварительно загрузил с таблицами SQLite, отображаются нормально, а функции приложения ожидаются. Проблема возникает, когда я загружаю данные JSON из удаленной базы данных, чтобы заменить локальную информацию, хранящуюся на устройстве iOS. Я буду упрощать, ссылаясь на одну таблицу:
// Create an object, reading its information from the local database.
Pregunta *objPregunta = [[Pregunta alloc] initWithPrimaryKey:0 database:delegate.database];
// Erase all data in the object's table (preguntas) see method below.
[objPregunta deleteAllFromDatabase];
// Obtain the remote objects retrieved via JSON, and cycle them.
NSArray *preguntas = (NSArray *)[responseDict objectForKey:@"preguntas"];
for (id pregunta in preguntas) {
// Create a dictionary storing the JSON object.
NSDictionary *pregunta_dict = (NSDictionary *) pregunta;
// Send the dictionary to the function for SQLite insertion.
[objPregunta insertNewRecordIntoDatabase:pregunta_dict];
}
// Free the object resources.
[objPregunta release];
Это функция удаления SQLite, связанная с объектом Pregunta в приведенном выше коде:
- (void) deleteAllFromDatabase {
if(delete_statement == nil) {
const char *sql = "DELETE FROM preguntas";
if (sqlite3_prepare_v2(database, sql, -1, &delete_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: Failed to prepare SQL statement: %s.", sqlite3_errmsg(database));
}
}
if (sqlite3_step(delete_statement) != SQLITE_DONE) {
NSAssert1(0, @"Failed to save priority with message: %s.", sqlite3_errmsg(database));
}
sqlite3_reset(delete_statement);
}
И, наконец, это функция, которая вставляет новую запись в базу данных, используя переданный ей объект словаря:
- (void) insertNewRecordIntoDatabase:(NSDictionary *)pregunta_dict {
if (insert_statement == nil) {
const char *sql = "INSERT INTO preguntas (id_forma, numero, seccion, texto, respuesta, comentario, requiere_fotografia, fotografia, tipo) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)";
self.id_forma = [[pregunta_dict objectForKey:@"id_forma"] integerValue];
self.numero = [[pregunta_dict objectForKey:@"numero"] integerValue];
if([pregunta_dict objectForKey:@"seccion"] == [NSNull null]) {
self.seccion = nil;
} else {
self.seccion = [pregunta_dict objectForKey:@"seccion"];
}
self.texto = [pregunta_dict objectForKey:@"texto"];
if([pregunta_dict objectForKey:@"respuesta"] == [NSNull null]) {
self.respuesta = nil;
} else {
self.respuesta = [pregunta_dict objectForKey:@"respuesta"];
}
if([pregunta_dict objectForKey:@"comentario"] == [NSNull null]) {
self.comentario = nil;
} else {
self.comentario = [pregunta_dict objectForKey:@"comentario"];
}
self.requiere_fotografia = [pregunta_dict objectForKey:@"requiere_fotografia"];
if([pregunta_dict objectForKey:@"fotografia"] == [NSNull null]) {
self.fotografia = nil;
} else {
self.fotografia = [pregunta_dict objectForKey:@"fotografia"];
}
self.tipo = [pregunta_dict objectForKey:@"tipo"];
if (sqlite3_prepare_v2(database, sql, -1, &insert_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: Failed to prepare SQL statement: %s.", sqlite3_errmsg(database));
} else {
@try {
sqlite3_bind_int (insert_statement, 1, self.id_forma);
sqlite3_bind_int (insert_statement, 2, self.numero);
sqlite3_bind_text(insert_statement, 3, [self.seccion UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 4, [self.texto UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 5, [self.respuesta UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 6, [self.comentario UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 7, [self.requiere_fotografia UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 8, [self.fotografia UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 9, [self.tipo UTF8String], -1, SQLITE_TRANSIENT);
}
@catch (NSException *exception) {
;
}
}
}
if (sqlite3_step(insert_statement) != SQLITE_DONE) {
NSAssert1(0, @"Failed to prepare SQL statement: %s.", sqlite3_errmsg(database));
} else {
NSLog(@"Pregunta insert_id: %lld", sqlite3_last_insert_rowid(database));
}
sqlite3_reset(insert_statement);
}
Теперь проблема с кодом состоит в том, что каким-то образом кажется, что он вставляет строки неправильно, потому что, когда процессы удаления / вставки завершаются для всех таблиц, и я читаю данные, вставленные из SQLite, я получаю дублированные значения в база данных.
Я думал, что это как-то связано с функцией deleteAllFromDatabase
, но, опять же, это кажется слишком простым, чтобы вызывать какие-либо проблемы. Я также попытался напрямую указать, какие значения я хочу сохранить для первичных ключей, но приложение вылетает из-за того, что, по-видимому, ограничение не выполняется (у меня нет внешних ключей, только первичный ключ в каждой таблице).
Какие предложения у вас, ребята, есть? Пожалуйста, не обращайте внимания на пустые блоки catch, я протестировал их и удалил их код, чтобы я мог сократить их здесь в источнике, который я публикую для вас. Кроме того, операторы являются локальными статическими переменными для класса, который я повторно использую и сбрасываю при необходимости.
Спасибо за любой вклад, который вы можете предоставить. Я буду публиковать любые дополнительные сведения, которые вам могут понадобиться для раскрытия, чтобы лучше понять, что я делаю.
Вот некоторые выводы, которые мне удалось поймать:
Поскольку я отображаю строки в TableView, я вижу, что все
значения в таблице базы данных точно такие же (я также
NSLogged их), за исключением первичного ключа (который автоматически генерируется
SQLite INTEGER AUTOINCREMENT) ... так что это, вероятно, означает, что есть
что-то не так с моими инструкциями по вставке или способом отправки
словарные данные для каждой вставляемой строки.
Что касается данных в ресурсе JSON, то проблем вообще нет
с его помощью я захватил всю строку, отступил и отобразил
это, чтобы проверить полную целостность информации, и все это соответствует
что из удаленных таблиц MySQL.
В первом блоке кода цикл foreach гласит: for (id pregunta in preguntas) {
, однако в этой статье вы обнаружите, что вместо них используется for (id *item in items) {
(с * в качестве указателя для ). Я пытался сделать его похожим, но я получаю сообщение об ошибке, и код не будет компилироваться, несмотря ни на что.
Есть ли вероятность, что мне потребуется каким-то образом сбросить DSDictionary
, который я передам функции insertNewRecordIntoDatabase:
, чтобы она не содержала предыдущих значений? Я бы предположил, что для каждой итерации данные будут разными, но это доказывает, что я ошибаюсь.