SQLite внезапно не отвечает в приложении iPhone - PullRequest
0 голосов
/ 17 июня 2011

У меня огромная проблема с SQLite в приложении для iPhone, которая должна быть скоро исправлена ​​для клиента!По сути, я извлекаю столбец из базы данных и загружаю его в табличное представление на viewWillAppear.Он работает нормально, в первые несколько раз загружается представление, но затем он неожиданно начинает возвращать пустые (нулевые) значения.После проверки выясняется, что, возможно, существует проблема с открытием базы данных, но это мой первый проект на SQLite, поэтому трудно понять, что происходит.

Вот код, который я использую для извлечения информации SQL:

+ (void) getInitialDataToDisplay:(NSString *)dbPath {
 NSLog(@"INCOME CALLED 1");
NavTabAppDelegate *appDelegate = (NavTabAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.incomeArray = [[NSMutableArray alloc] init];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
    NSLog(@"INCOME CALLED 2");
    const char *sql = "select IncomeID, IncomeName from Income ORDER BY IncomeName asc";
    //const char *sql2 = "select categoryID, Size from coffee";
    sqlite3_stmt *selectstmt;




    if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
        NSLog(@"INCOME CALLED 3");
        while(sqlite3_step(selectstmt) == SQLITE_ROW) {
            NSLog(@"INCOME CALLED 4");
            NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
            Income *incomeObj = [[Income alloc] initWithPrimaryKey:primaryKey];

            //This is how I pull info from the database using the above select statement and setting it in the coffeeObj property of Coffee class
            incomeObj.incomeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
            //coffeeObj.coffeeSize = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)];

            incomeObj.isDirty = NO;

            [appDelegate.incomeArray addObject:incomeObj];

            [incomeObj release];
              NSLog(@"INCOME OBJECTS %@", incomeObj.incomeName);


            //NSLog(@"CALLED");


        }


    }



}

else{
    sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory
     NSLog(@"INCOME CALLED 5");
}
NSLog(@"INCOME CALLED 6");

}

Я вызываю код в viewWillAppear следующим образом:

[Income getInitialDataToDisplay:[appDelegate getDBPath]];

Также это вывод из моей консоли при возникновении ошибки:

    2011-06-17 12:21:48.307 CashCal[318:707] GET DB PATH CALLED
2011-06-17 12:21:48.310 CashCal[318:707] /var/mobile/Applications/2BD7CA1D-C7AB-4425-B5C1-974C4F4D057C/Documents/SQL.sqlite
2011-06-17 12:21:48.312 CashCal[318:707] INCOME CALLED 1
2011-06-17 12:21:48.314 CashCal[318:707] INCOME CALLED 5
2011-06-17 12:21:48.318 CashCal[318:707] INCOME CALLED 6

Похоже, проблема в первом операторе if, открывающем базу данных.Мне действительно нужна помощь в этом

Ответы [ 4 ]

1 голос
/ 17 июня 2011

Вы всегда должны уничтожать подготовленные операторы, вызывая sqlite3_finalize (your_stmt).И вы всегда должны закрывать ваше соединение, не только в случае сбоя sqlite3_open ().

Также сделайте что-то вроде этого:

if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
 //your code here
} else {
 //print error
 NSLog(@"sql-error: %s", sqlite3_errmsg(database));
}

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


DBi.h

#import <Foundation/Foundation.h>
#import <sqlite3.h>

@interface DBi : NSObject {
    sqlite3* db;
}

- (void)opendDB;
- (void)closeDB;
- (NSArray*)getIcons;
@end

DBi.m

#import "DBi.h"
#import "Income.h"

static DBi *sharedDBi = nil;

@implementation DBi

- (void)dealloc {
    sqlite3_close(db);
    [super dealloc];
}


+ (DBi*)sharedManager {
    if (sharedDBi == nil) {
        sharedDBi = [[super allocWithZone:NULL] init];
        [sharedDBi opendDB];
    }
    return sharedDBi;
}

+ (id)allocWithZone:(NSZone *)zone {
    return [[self sharedManager] retain];
}

- (void)opendDB {
    NSString *dbPath = [[NSBundle mainBundle]pathForResource:@"path_to_db_file"ofType:@"sqlite"];
    //open the database
    if(!sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK) {
        NSLog(@"connection to db failed");
        sqlite3_close(db);
    }
}

- (void)closeDB {
    sqlite3_close(db);
}

- (NSArray*)getIncoms { 
    NSMutableArray rArray = [[[NSMutableArray alloc] init] autorelease];

    const char *sql = "select IncomeID, IncomeName from Income ORDER BY IncomeName asc";
    //const char *sql2 = "select categoryID, Size from coffee";
    sqlite3_stmt *selectstmt;

    if(sqlite3_prepare_v2(db, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
        while(sqlite3_step(selectstmt) == SQLITE_ROW) {
            NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
            Income *incomeObj = [[Income alloc] initWithPrimaryKey:primaryKey];
            incomeObj.incomeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];                
            incomeObj.isDirty = NO;
            [rArray addObject:incomeObj];
            [incomeObj release];    
        }        
     } else {
        NSLog(@"sql-error in getIncoms: %s", sqlite3_errmsg(db));
     }
     sqlite3_finalize(selectstmt);

    return rArray;
}

Теперь вы можете сделать что-то подобное.

DBi *dbi = [[DBi alloc] init];
NSArray *incoms = [dbi getIncoms];
[dbi release];

надеюсь, это должно помочь

0 голосов
/ 21 июня 2011

Оказывается, я вызывал один и тот же метод SQL в двух разных местах очень быстро, прежде чем операторы имели возможность каждый раз завершаться. Я предполагаю, что это вызвало какое-то совпадение, которое в итоге привело к тому, что утверждения стали недействительными. Спасибо за помощь. Я определенно буду использовать CoreData или FMDB в следующий раз.

0 голосов
/ 17 июня 2011

Используйте FMDB для ваших задач sqlite.Это плохая практика - использовать вызовы sqlite везде в приложении.Просто найдите в Google для FMDB Пример, вы найдете один.FMDB намного проще реализовать, чем SQLIte, потому что FMDB обрабатывает все.

0 голосов
/ 17 июня 2011
use this code
    sqlite3 *database;

    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) 
    {   
        ////your Code

        if(sqlite3_prepare_v2(database, [sqlStatement cStringUsingEncoding:NSUTF8StringEncoding], -1, &compiledStatement, NULL) == SQLITE_OK) 
        {
            NSLog(@"%@",sqlStatement);

            while(sqlite3_step(compiledStatement) == SQLITE_ROW) 
            {
                //your code
            }       
        }
        sqlite3_finalize(compiledStatement);
            sqlite3_close(database);
    }       
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...