在iOS上使用和访问现有的SQLite数据库
我在SQLite中有一个完全填充的数据库,我想在我的新应用程序中使用它。 这是相当大的,所以我想避免把它改成另一种格式,如果可能的话。 我怎样才能使用这个数据库的方式,它随我的应用程序?
编辑:如果我只是将文件放入我的支持的文件目录,例如,我如何访问它? 我如何参考?
通过使用FBDB Framework
SQLite数据库交互可以变得简单和干净。 FMDB是SQLite C接口的Objective-C包装器。
参考值得阅读:
FMDB框架文档
示例项目与故事板
初始设置
像应用程序捆绑包中的任何其他文件一样添加SQLite DB
数据库,然后使用以下代码将数据库复制到文档目录,然后使用文档目录中的数据库
- 首先下载FMDB框架
- 现在提取框架从
src/fmdb
文件夹(不是src/sample
或src/extra
文件夹)复制所有文件。 - 点击Xcode左栏中的项目。
- 点击中间一列的主要目标。
- 点击“Build Phases”标签。
- 展开“与库链接二进制文件”旁边的箭头。
- 点击“+”button。
- searchlibsqlite3.0.dylib并双击它。
将existing database
复制到didFinishLaunchingWithOptions:
app's document
中didFinishLaunchingWithOptions:
并维护整个应用程序的数据库path。
在你的AppDelegate中添加下面的代码。
AppDelegate.m
#import "AppDelegate.h" @implementation AppDelegate // Application Start - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Function called to create a copy of the database if needed. [self createCopyOfDatabaseIfNeeded]; return YES; } #pragma mark - Defined Functions // Function to Create a writable copy of the bundled default database in the application Documents directory. - (void)createCopyOfDatabaseIfNeeded { // First, test for existence. BOOL success; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // Database filename can have extension db/sqlite. NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *appDBPath = [documentsDirectory stringByAppendingPathComponent:@"database-name.sqlite"]; success = [fileManager fileExistsAtPath:appDBPath]; if (success) { return; } // The writable database does not exist, so copy the default to the appropriate location. NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"database-name.sqlite"]; success = [fileManager copyItemAtPath:defaultDBPath toPath:appDBPath error:&error]; NSAssert(success, @"Failed to create writable database file with message '%@'.", [error localizedDescription]); }
YourViewController.m
select查询
#import "FMDatabase.h" - (void)getAllData { // Getting the database path. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docsPath = [paths objectAtIndex:0]; NSString *dbPath = [docsPath stringByAppendingPathComponent:@"database-name.sqlite"]; FMDatabase *database = [FMDatabase databaseWithPath:dbPath]; [database open]; NSString *sqlSelectQuery = @"SELECT * FROM tablename"; // Query result FMResultSet *resultsWithNameLocation = [database executeQuery:sqlSelectQuery]; while([resultsWithNameLocation next]) { NSString *strID = [NSString stringWithFormat:@"%d",[resultsWithNameLocation intForColumn:@"ID"]]; NSString *strName = [NSString stringWithFormat:@"%@",[resultsWithNameLocation stringForColumn:@"Name"]]; NSString *strLoc = [NSString stringWithFormat:@"%@",[resultsWithNameLocation stringForColumn:@"Location"]]; // loading your data into the array, dictionaries. NSLog(@"ID = %d, Name = %@, Location = %@",strID, strName, strLoc); } [database close]; }
插入查询
#import "FMDatabase.h" - (void)insertData { // Getting the database path. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docsPath = [paths objectAtIndex:0]; NSString *dbPath = [docsPath stringByAppendingPathComponent:@"database-name.sqlite"]; FMDatabase *database = [FMDatabase databaseWithPath:dbPath]; [database open]; NSString *insertQuery = [NSString stringWithFormat:@"INSERT INTO user VALUES ('%@', %d)", @"Jobin Kurian", 25]; [database executeUpdate:insertQuery]; [database close]; }
更新查询
- (void)updateDate { // Getting the database path. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docsPath = [paths objectAtIndex:0]; NSString *dbPath = [docsPath stringByAppendingPathComponent:@"fmdb-sample.sqlite"]; FMDatabase *database = [FMDatabase databaseWithPath:dbPath]; [database open]; NSString *insertQuery = [NSString stringWithFormat:@"UPDATE users SET age = '%@' WHERE username = '%@'", @"23", @"colin" ]; [database executeUpdate:insertQuery]; [database close]; }
删除查询
#import "FMDatabase.h" - (void)deleteData { // Getting the database path. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docsPath = [paths objectAtIndex:0]; NSString *dbPath = [docsPath stringByAppendingPathComponent:@"database-name.sqlite"]; FMDatabase *database = [FMDatabase databaseWithPath:dbPath]; [database open]; NSString *deleteQuery = @"DELETE FROM user WHERE age = 25"; [database executeUpdate:deleteQuery]; [database close]; }
加法function
获得行数
确保包含FMDatabaseAdditions.h
文件以使用intForQuery:
#import "FMDatabase.h" #import "FMDatabaseAdditions.h" - (void)gettingRowCount { // Getting the database path. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docsPath = [paths objectAtIndex:0]; NSString *dbPath = [docsPath stringByAppendingPathComponent:@"database-name.sqlite"]; FMDatabase *database = [FMDatabase databaseWithPath:dbPath]; [database open]; NSUInteger count = [database intForQuery:@"SELECT COUNT(field_name) FROM table_name"]; [database close]; }
像应用程序包中的任何其他文件一样添加Sqlite数据库
通过代码将其复制到文档目录并使用它。这样做的目的是更新sqlite中的内容仅在Documents目录中是可能的
-(void) checkAndCreateDatabase { // Check if the SQL database has already been saved to the users phone, if not then copy it over BOOL success; // Create a FileManager object, we will use this to check the status // of the database and to copy it over if required NSFileManager *fileManager = [NSFileManager defaultManager]; // Check if the database has already been created in the users filesystem success = [fileManager fileExistsAtPath:_databasePath]; // If the database already exists then return without doing anything if(success) return; // If not then proceed to copy the database from the application to the users filesystem // Get the path to the database in the application package NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:_databaseName]; // Copy the database from the package to the users filesystem [fileManager copyItemAtPath:databasePathFromApp toPath:_databasePath error:nil]; } - (id)init { if ((self = [super init])) { _databaseName = DB_NAME; NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [documentPaths objectAtIndex:0]; _databasePath = [documentsDir stringByAppendingPathComponent:_databaseName]; if (sqlite3_open([[self dbPath] UTF8String], &_database) != SQLITE_OK) { [[[UIAlertView alloc]initWithTitle:@"Missing" message:@"Database file not found" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]show]; } } return self; }
使用swift,singleton类和FMDB。 你可以使用下面的代码来实现它很容易。
下载示例
import Foundation class LocalDatabase: NSObject { //sharedInstance static let sharedInstance = LocalDatabase() func methodToCreateDatabase() -> NSURL? { let fileManager = NSFileManager.defaultManager() let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) if let documentDirectory:NSURL = urls.first { // No use of as? NSURL because let urls returns array of NSURL // exclude cloud backup do { try documentDirectory.setResourceValue(true, forKey: NSURLIsExcludedFromBackupKey) } catch _{ print("Failed to exclude backup") } // This is where the database should be in the documents directory let finalDatabaseURL = documentDirectory.URLByAppendingPathComponent("contact.db") if finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) { // The file already exists, so just return the URL return finalDatabaseURL } else { // Copy the initial file from the application bundle to the documents directory if let bundleURL = NSBundle.mainBundle().URLForResource("contact", withExtension: "db") { do { try fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL) } catch _ { print("Couldn't copy file to final location!") } } else { print("Couldn't find initial database in the bundle!") } } } else { print("Couldn't get documents directory!") } return nil } func methodToInsertUpdateDeleteData(strQuery : String) -> Bool { // print("%@",String(methodToCreateDatabase()!.absoluteString)) let contactDB = FMDatabase(path: String(methodToCreateDatabase()!.absoluteString) ) if contactDB.open() { let insertSQL = strQuery let result = contactDB.executeUpdate(insertSQL, withArgumentsInArray: nil) if !result { print("Failed to add contact") print("Error: \(contactDB.lastErrorMessage())") return false } else { print("Contact Added") return true } } else { print("Error: \(contactDB.lastErrorMessage())") return false } } func methodToSelectData(strQuery : String) -> NSMutableArray { let arryToReturn : NSMutableArray = [] print("%@",String(methodToCreateDatabase()!.absoluteString)) let contactDB = FMDatabase(path: String(methodToCreateDatabase()!.absoluteString) ) if contactDB.open() { let querySQL = strQuery let results:FMResultSet? = contactDB.executeQuery(querySQL, withArgumentsInArray: nil) while results?.next() == true { arryToReturn.addObject(results!.resultDictionary()) } // NSLog("%@", arryToReturn) if arryToReturn.count == 0 { print("Record Not Found") } else { print("Record Found") } contactDB.close() } else { print("Error: \(contactDB.lastErrorMessage())") } return arryToReturn } }
有一个快乐的编码。
要复制目录中的.sqlite文件…
BOOL success; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // Database filename can have extension db/sqlite. NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:@"MapView.sqlite"]; success = [fileManager fileExistsAtPath:databasePath]; // if (success){ // return; // } // The writable database does not exist, so copy the default to the appropriate location. NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"MapView.sqlite"]; success = [fileManager copyItemAtPath:defaultDBPath toPath:databasePath error:&error]; if (!success) { //NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]); } else { NSLog(@"Database created successfully"); }
从数据库中select数据…
const char *dbpath = [databasePath UTF8String]; sqlite3_stmt *statement; if (sqlite3_open(dbpath, &mapDB) == SQLITE_OK) { NSString *querySQL = [NSString stringWithFormat: @"SELECT * FROM maplatlong"]; const char *query_stmt = [querySQL UTF8String]; if (sqlite3_prepare_v2(mapDB, query_stmt, -1, &statement, NULL) == SQLITE_OK) { while(sqlite3_step(statement) == SQLITE_ROW) { NSString *cityN = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)]; NSString *lat = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)]; NSString *longi = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)]; [cityName addObject:cityN]; [latitude addObject:lat]; [longitude addObject:longi]; } sqlite3_finalize(statement); } sqlite3_close(mapDB); }
这下面的方法将帮助你处理数据库
如果不存在,则在文档目录中复制数据库的方法
-(void)copyDatabase { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *insPath = [NSString stringWithFormat:@"Instamontage.sqlite"]; destPath = [documentsDirectory stringByAppendingPathComponent:insPath]; NSString *srcPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:insPath]; // NSLog(@"\n src %@ \n dest %@", srcPath, destPath); if (![[NSFileManager defaultManager] fileExistsAtPath:destPath]) { NSError *error; NSLog(@"not exist"); [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:destPath error:&error]; } else { NSLog(@"exist"); } }
插入/删除/更新表的方法
-(BOOL)dataManipulation: (NSString *)query { BOOL result=NO; if (sqlite3_open([destPath UTF8String], &connectDatabase)==SQLITE_OK) { sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connectDatabase, [query UTF8String], -1, &stmt, NULL)==SQLITE_OK) { sqlite3_step(stmt); result=YES; } sqlite3_finalize(stmt); } sqlite3_close(connectDatabase); return result; }
从表中获取行的方法
-(NSMutableArray *)getData: (NSString *)query { NSMutableArray *arrData=[[NSMutableArray alloc]init]; if (sqlite3_open([destPath UTF8String],&connectDatabase)==SQLITE_OK) { sqlite3_stmt *stmt; const char *query_stmt = [query UTF8String]; if (sqlite3_prepare_v2(connectDatabase,query_stmt, -1, &stmt, NULL)==SQLITE_OK) { while (sqlite3_step(stmt)==SQLITE_ROW) { NSMutableDictionary *dictResult=[[NSMutableDictionary alloc] init]; for (int i=0;i<sqlite3_column_count(stmt);i++) { NSString *str; if (sqlite3_column_text(stmt,i)!=NULL) { str = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt,i)]; } else { str=@""; } [dictResult setValue:str forKey:[NSString stringWithUTF8String:(char *)sqlite3_column_name(stmt,i)]]; } [arrData addObject:dictResult]; } sqlite3_finalize(stmt); } sqlite3_close(connectDatabase); } return arrData; }
- 枚举值为NSString(iOS)
- 必须在App Store发布时增加哪些iOS应用程序版本/内部版本号?
- NSCameraUsageDescription在iOS 10.0运行时崩溃?
- UITableView单元格select颜色?
- AutoLayout + RTL + UILabel文本alignment
- Xcode只能重构C和Objective-C的代码。 如何重命名在Xcode 6中的Swift类名?
- 将转义的UTF8字符转换回原来的forms
- Objective-C ARC:强大vs保留和弱与分配
- Xcode 5.1 – 无需编译的架构(ONLY_ACTIVE_ARCH = YES,活动arch = x86_64,VALID_ARCHS = i386)