在iOS開發(fā)過程中,會(huì)經(jīng)常使用到數(shù)據(jù)存儲.數(shù)據(jù)存儲有好幾種常見的方式:plist存儲,偏好設(shè)置,歸檔,數(shù)據(jù)庫等,該篇文章是我想做個(gè)記錄,也想和大家分享下自己的一些見解,涉及的內(nèi)容不是很深,只做實(shí)用性的參考.如果哪位大神對此有深入研究,可以留下來深入討論下,我請吃飯.
沙盒
- iOS的存儲都是存在沙盒中的,應(yīng)用程序只能訪問自己的沙盒
- 沙盒目錄里有三個(gè)文件:Documents, Library, tmp
沙盒目錄圖
- Documents:用于存儲用戶數(shù)據(jù)或其它應(yīng)該定期備份的信息
- 注意,該文件中的內(nèi)容會(huì)在手機(jī)連接電腦時(shí)進(jìn)行同步到云上,所以蘋果不建議開發(fā)者將大量的數(shù)據(jù)寫入到該文件中.如果將視頻圖片等大量的數(shù)據(jù)存入到該文件中,會(huì)被蘋果拒的
// Documents獲取方式
NSString *docStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
- Library:該目錄下有兩個(gè)子目錄,Caches和Preferences.
- Caches:一般用于存放應(yīng)用程序?qū)S玫闹С治募?保存應(yīng)用程序再次啟動(dòng)所需要的信息
- 數(shù)據(jù)存在該文件中
//Caches獲取方法
NSString *cachesStr = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
- Preferences:存放應(yīng)用程序的偏好設(shè)置的文件.
- tmp:用于存放臨時(shí)文件,當(dāng)程序退出時(shí)該文件中的數(shù)據(jù)會(huì)被清空
//tmp獲取方式
NSString *tmpStr = NSTemporaryDirectory();
關(guān)于沙盒的詳細(xì)信息,可以去搜下別人的文章,我發(fā)現(xiàn)有很多文章對沙盒有詳細(xì)的講解的,或者參考蘋果官方文檔:About Files and Directories
Plist存儲
定義:plist文件的全名是:Property List解藻,它是一種用來存儲串行化后的對象的文件。文件的擴(kuò)展名是.plist葡盗,通常就稱為plist文件.主要是用來存儲一些OC對象,比如NSArray/NSDictionary,不能存放自定義對象.一般常用的Foundation對象有NSString, NSData, NSDate, NSNumber, NSArray, NSDictionary
存儲原理:寫入沙盒.只要有writeToFile的對象螟左,就能進(jìn)行plist存儲,調(diào)用writeToFile就能自動(dòng)生成plist格式的文件
注意:plist存儲觅够,不能存儲自定義對象胶背,會(huì)失敗的。
plist文件在數(shù)據(jù)更新的時(shí)候需要先取出然后修改在存儲
常用方法:
// 寫入方法
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atomically;
// 取出 字典
+ (nullable NSDictionary<KeyType, ObjectType> *)dictionaryWithContentsOfFile:(NSString *)path;
+ (nullable NSDictionary<KeyType, ObjectType> *)dictionaryWithContentsOfURL:(NSURL *)url;
// 取出 數(shù)組
+ (nullable NSMutableArray<ObjectType> *)arrayWithContentsOfFile:(NSString *)path;
+ (nullable NSMutableArray<ObjectType> *)arrayWithContentsOfURL:(NSURL *)url;
獲取沙盒路徑
NSString *str = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
偏好設(shè)置
在開發(fā)中偏好設(shè)置用的還是比較多的,存取比較方便,不需要關(guān)心文件名,其實(shí)底層是利用字典存儲一些鍵值對,你可以存儲后打開路徑文件看一下.
存儲過程是用NSUserDefaults的單利調(diào)用setObject:forKey進(jìn)行存儲.
注意:不能存儲對象,不能及時(shí)存儲,需要做同步操作喘先,把內(nèi)存中的數(shù)據(jù)同步到硬盤上钳吟。
簡單使用
// 存儲名字jack到沙盒中,存儲的key是 @"name"
[[NSUserDefaults standardUserDefaults] setObject:@"jack" forKey:@"name"];
// 同步
[[NSUserDefaults standardUserDefaults] synchronize];
// 用key @"name" 從沙盒中取出名字
NSString *str =[[NSUserDefaults standardUserDefaults] objectForKey:@"name"];
存儲方法:
// 存儲方法(set開頭)
- (void)setObject:(nullable id)value forKey:(NSString *)defaultName;
- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName;
- (void)setFloat:(float)value forKey:(NSString *)defaultName;
- (void)setDouble:(double)value forKey:(NSString *)defaultName;
- (void)setBool:(BOOL)value forKey:(NSString *)defaultName;
- (void)setURL:(nullable NSURL *)url forKey:(NSString *)defaultName
讀取數(shù)據(jù)的方法:
// 讀取數(shù)據(jù)的方法
- (nullable id)objectForKey:(NSString *)defaultName;
- (nullable NSString *)stringForKey:(NSString *)defaultName;
- (nullable NSArray *)arrayForKey:(NSString *)defaultName;
- (nullable NSDictionary<NSString *, id> *)dictionaryForKey:(NSString *)defaultName;
- (nullable NSData *)dataForKey:(NSString *)defaultName;
- (nullable NSArray<NSString *> *)stringArrayForKey:(NSString *)defaultName;
- (NSInteger)integerForKey:(NSString *)defaultName;
- (float)floatForKey:(NSString *)defaultName;
- (double)doubleForKey:(NSString *)defaultName;
- (BOOL)boolForKey:(NSString *)defaultName;
- (nullable NSURL *)URLForKey:(NSString *)defaultName NS_AVAILABLE(10_6, 4_0);
刪除數(shù)據(jù):
// 刪除數(shù)據(jù)
- (void)removeObjectForKey:(NSString *)defaultName;
歸檔
個(gè)人理解,歸檔的過程就是一個(gè)序列化的過程,然后存儲到指定的路徑路徑文件.歸檔可以存儲對象,需要遵守NSCoding協(xié)議,然后重寫下面兩種方法
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder; // NS_DESIGNATED_INITIALIZER
具體使用方法:
- 自定義模型
Person類的.h文件
#import <UIKit/UIKit.h>
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) NSInteger age;
@end
Person類的.m文件
#import "Person.h"
@interface Person ()<NSCoding>
@end
@implementation Person
// 解檔
// 從一個(gè)給定unarchiver的數(shù)據(jù)中返回一個(gè)初始化對象。
- (instancetype)initWithCoder:(NSCoder *)decoder{
if (self = [super init]) {
self.name = [decoder decodeObjectForKey:@"name"];
self.age = [decoder decodeIntegerForKey:@"age"];
self.height = [decoder decodeFloatForKey:@"height"];
}
return self;
}
// 歸檔
/**
通過一個(gè)給定的archiver把消息接收者進(jìn)行編碼窘拯。
當(dāng)接收到encodeObject消息的時(shí)候红且,類終端encodeWithCoder方法被調(diào)用坝茎。
*/
- (void)encodeWithCoder:(NSCoder *)coder{
[coder encodeObject:self.name forKey:@"name"];
[coder encodeInteger:self.age forKey:@"age"];
[coder encodeFloat:self.height forKey:@"height"];
}
- 第一種用法
// 創(chuàng)建對象
Person *person = [Person new];
person.name = @"jack";
person.age = 20;
person.height = 180.0f;
// 獲取路徑
NSString *str = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"123.archiver"];
// 歸檔
BOOL flag = [NSKeyedArchiver archiveRootObject:person toFile:filePath];
if (flag) {
NSLog(@"歸檔成功");
}else{
NSLog(@"歸檔失敗");
}
// 解檔
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:str];
- 第二種用法
// 創(chuàng)建對象
Person *person = [Person new];
person.name = @"jack";
person.age = 20;
person.height = 180.0f;
// 歸檔成二進(jìn)制 (可以用偏好設(shè)置保存或者直接寫入到沙盒)
NSData *dataArc = [NSKeyedArchiver archivedDataWithRootObject:person];
[[NSUserDefaults standardUserDefaults] setObject:dataArc forKey:@"archiver"];
[[NSUserDefaults standardUserDefaults] synchronize];
// 解檔
NSData *dataUn = [[NSUserDefaults standardUserDefaults] objectForKey:@"archiver"];
Person *unPerson = [NSKeyedUnarchiver unarchiveObjectWithData:dataUn];
- 第三種用法
// 獲取路徑
NSString *str = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"123.archiver"];
// 創(chuàng)建一個(gè)二進(jìn)制對象
NSMutableData *data = [[NSMutableData alloc] init];
// 設(shè)置歸檔寫入對象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
// 歸檔
[archiver encodeObject:person forKey:@"archiver"];// archivingDate的encodeWithCoder方法被調(diào)用
[archiver finishEncoding];
// 保存二進(jìn)制到沙盒中
[data writeToFile:str atomically:YES];
// 解檔
// 通過文件獲取一個(gè)二進(jìn)制對象
NSMutableData *data = [[NSMutableData alloc] initWithContentsOfFile:str];
// 讀取二進(jìn)制文件
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
// 獲得類
Person *person = [unarchiver decodeObjectForKey:@"person"]; ;// initWithCoder方法被調(diào)用
[unarchiver finishDecoding];
在自定義模型的.m文件中,重寫 - (instancetype)initWithCoder:(NSCoder *)decoder 時(shí),調(diào)用的是[super init], 而不是 [super initWithCoder:decoder]; 這是因?yàn)镻erson類繼承的是NSObject,NSObject類沒有遵守NSCoding這個(gè)協(xié)議.
initWithCoder原理:只要解析文件就會(huì)調(diào)用,xib,storyboard都是文件暇番,因此只要解析這兩個(gè)文件嗤放,就會(huì)調(diào)用initWithCoder。
因此如果在storyboard使用自定義view,重寫initWithCoder方法壁酬,一定要調(diào)用[super initWithCoder:]次酌,因?yàn)橹挥邢到y(tǒng)才知道怎么解析storyboard,如果沒有調(diào)用舆乔,就解析不了這個(gè)文件岳服。
重寫NSCoding協(xié)議的方法時(shí)有一個(gè)不便的地方就是,當(dāng)自定義模型特別多的時(shí)候,每個(gè).m文件中都需要重寫一遍,挺麻煩的.下面這個(gè)文件是通過運(yùn)行時(shí)的方法遍歷模型中的屬性進(jìn)行設(shè)置的,在使用的時(shí)候,需要導(dǎo)入#import "GGArchiverCoding.h", #import <objc/runtime.h>頭文件,在.m文件中寫入這句話就可以了:NSCodingImplementation;
GGArchiverCoding.h 文件
注意:該文件可以原版copy的
#define NSCodingImplementation \
- (instancetype)initWithCoder:(NSCoder *)aDecoder{\
if (self = [super init]) { \
unsigned int count; \
Ivar *ivarList = class_copyIvarList([self class], &count);\
for (int i = 0; i < count; i++) {\
Ivar ivar = ivarList[i];\
const char *ivarName = ivar_getName(ivar);\
NSString *key = [NSString stringWithUTF8String:ivarName];\
id value = [aDecoder decodeObjectForKey:key]; \
[self setValue:value forKey:key];\
}\
}\
return self;\
}\
- (void)encodeWithCoder:(NSCoder *)aCoder{ \
unsigned int count;\
Ivar *ivarList = class_copyIvarList([self class], &count);\
for (int i = 0; i < count; i++) {\
Ivar ivar = ivarList[i];\
const char *ivarName = ivar_getName(ivar);\
NSString *key = [NSString stringWithUTF8String:ivarName];\
id value = [self valueForKeyPath:key];\
[aCoder encodeObject:value forKey:key];\
}\
}
iOS中最常見的三種存儲方式介紹完了,雖然使用率還是蠻好的,對于大型數(shù)據(jù)的存儲上面三種就做不到了,或者說想做的很麻煩的.數(shù)據(jù)庫就能這解決這種問題
SQLite介紹(PS:下面只是對SQLite3的簡單實(shí)用的介紹,沒有做詳細(xì)的講解,事后詳情再補(bǔ)上.如果哪位大神有詳細(xì)介紹的文章,可以跟帖鏈接,共同學(xué)習(xí))
實(shí)際開發(fā)過程中,很少會(huì)直接用SQLite3,常常會(huì)采用一些對SQLite3封裝好的三方框架,FMDB就是一個(gè)非常優(yōu)秀的框架.
(度娘介紹):SQLite是一款輕型的嵌入式數(shù)據(jù)庫,它占用資源非常的低,在嵌入式設(shè)備中希俩,可能只需要幾百K的內(nèi)存就夠了,它的處理速度比Mysql派阱、PostgreSQL這兩款著名的數(shù)據(jù)庫都還快,數(shù)據(jù)庫(Database)是按照數(shù)據(jù)結(jié)構(gòu)來組織、存儲和管理數(shù)據(jù)的倉庫.
想學(xué)習(xí)數(shù)據(jù)就,建議安裝下Navicat,用著很不錯(cuò)的一款數(shù)據(jù)庫軟件.
數(shù)據(jù)庫可以分為兩大種類:關(guān)系型數(shù)據(jù)庫(主流)和 對象型數(shù)據(jù)庫
常用關(guān)系型數(shù)據(jù)庫PC端:Oracle斜纪、MySQL、SQL Server文兑、Access盒刚、DB2、Sybase.嵌入式\移動(dòng)客戶端:SQLite
數(shù)據(jù)庫的存儲結(jié)構(gòu)和excel很像绿贞,以表(table)為單位
數(shù)據(jù)庫的每一列叫字段(column因块,列,屬性)
每一行叫記錄(row籍铁,record涡上,每行存放多個(gè)字段對應(yīng)的值)
建表:Tabel Name: 填寫表明,建議以_t開頭
常用的關(guān)鍵字有:select、insert拒名、update吩愧、delete、from增显、create雁佳、where、desc同云、order糖权、by、group炸站、table星澳、alter、view旱易、index等等數(shù)據(jù)庫中不可以使用關(guān)鍵字來命名表禁偎、字段
- SQL語句種類:
- DDL:數(shù)據(jù)定義語句:包括create(創(chuàng)表)等操作
- DML:數(shù)據(jù)操作語句:包括:insert(增加)腿堤、update(修改)、delete(刪除)等操作
- DQL:數(shù)據(jù)查詢語句:最常用的關(guān)鍵字select(查詢),別的常用的關(guān)鍵字有where届垫,order by释液,group by和having
- 字段類型:SQL將數(shù)據(jù)劃分為四種數(shù)據(jù)類型
- integer : 整形值
- real:浮點(diǎn)值
- text:文本字符串
- blob:二進(jìn)制數(shù)據(jù)
- 主鍵:用來唯一標(biāo)識某一條記錄,在創(chuàng)表的時(shí)候用primary key聲明一個(gè)主鍵
創(chuàng)表
// 在編寫數(shù)據(jù)庫語句是,盡可能多的添加一些約束條件,這樣可以方便交流
// 導(dǎo)入數(shù)據(jù)庫頭文件
#import <sqlite3.h>
// 保存數(shù)據(jù)庫實(shí)例對象
@property (nonatomic, assign) sqlite3 *db;
// 獲取沙盒路徑
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"123.db"];
// 將OC字符串 轉(zhuǎn)成 C語言字符串
const char *cFilePath = filePath.UTF8String;
// 創(chuàng)表
// 將根據(jù)文件路徑打開數(shù)據(jù)庫,如果不存在装处,則會(huì)創(chuàng)建一個(gè)新的數(shù)據(jù)庫
// 返回值表示狀態(tài)
int result = sqlite3_open(cFilePath, &_db);
if (result == SQLITE_OK) {
NSLog(@"成功打開數(shù)據(jù)庫");
// 創(chuàng)表
const char *sql = "CREATE TABLE IF NOT EXISTS t_shop (id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, price integer NOT NULL);";
char *erroMsg = NULL;
// 創(chuàng)表語句 (exec:執(zhí)行sql語句)
sqlite3_exec(_db, sql, NULL, NULL, &erroMsg);
if (erroMsg) {
NSLog(@"創(chuàng)表失敗--%s", erroMsg);
}
}else{
NSLog(@"打開數(shù)據(jù)庫失敗");
}
// 移動(dòng)端在操作數(shù)據(jù)庫的時(shí)候一般不會(huì)考慮關(guān)閉
// 關(guān)閉數(shù)據(jù)庫:sqlite3_close(db);
增加數(shù)據(jù)
static int i = 0;
i++;
NSString *name = [NSString stringWithFormat:@"name-%d", i];
NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_shop (name, price) VALUES ('%@', %d);", name, i];
char *errMsg;
sqlite3_exec(self.db, sql.UTF8String, NULL, NULL, &errMsg);
NSLog(@"錯(cuò)誤信息 = %s", errMsg);
刪除數(shù)據(jù)
// 刪除price大于10的數(shù)據(jù)
NSString *sql = [NSString stringWithFormat:@"DELETE FROM t_shop where price > 10"];
char *errMsg;
sqlite3_exec(self.db, sql.UTF8String, NULL, NULL, NULL);
NSLog(@"錯(cuò)誤信息 = %s", errMsg);
修改數(shù)據(jù)
// price小于5,設(shè)置為0
NSString *sql = [NSString stringWithFormat:@"UPDATE t_shop set price = 0 where price < 5"];
char *errMsg;
sqlite3_exec(self.db, sql.UTF8String, NULL, NULL, &errMsg);
NSLog(@"%s", errMsg);
查詢數(shù)據(jù)
// 查詢數(shù)據(jù)如果用 sqlite3_exec(適合執(zhí)行沒有返回?cái)?shù)據(jù)的操作) 需要用到第三個(gè)參數(shù),函數(shù)的回調(diào)
// 查詢所有字段
const char *sql = "SELECT * FROM t_shop;";
// 準(zhǔn)備
// 第三個(gè)是sql長度, -1自動(dòng)計(jì)算
// stmt是用來取出查詢結(jié)果的
sqlite3_stmt *stmt = NULL;
int status = sqlite3_prepare_v2(self.db, sql, -1, &stmt, NULL);
if (status == SQLITE_OK) { // 準(zhǔn)備成功 -- SQL語句正確
// sqlite3_step 步驟(一步一步的執(zhí)行)
while (sqlite3_step(stmt) == SQLITE_ROW) { // 成功取出一條數(shù)據(jù)
// 后面的數(shù)字是列號
// 列好如果為0,代表的是主鍵的那列
const char *name = (const char *)sqlite3_column_text(stmt, 1);
const char *price = (const char *)sqlite3_column_text(stmt, 2);
NSLog(@"name = %s, price = %s", name, price);
}
}
FMDB簡單用法
FMDB是以0C的方式封裝了SQLite的C語言,用起來更加的面相對象,但是SQL語句還是需要寫的.這比起單純的使用SQLite3去做數(shù)據(jù)存儲已經(jīng)方便了很多,而且FMDB還對數(shù)據(jù)的存取操作做了線程安全的保證.
下載下來后的FMDB目錄結(jié)構(gòu)
在實(shí)際操作過程中,主要用到三個(gè)類
FMDatabase:一個(gè)FMDatabase對象就代表一個(gè)單獨(dú)的SQLite數(shù)據(jù)庫
FMResultSet:查詢后的結(jié)果集.
FMDatabaseQueue:用于在多個(gè)線程中執(zhí)行多個(gè)查詢或更新,保證線程安全的.
- 簡單用法
創(chuàng)建FMDatabase對象(打開數(shù)據(jù)庫)
// FMDB提供了兩個(gè)方法去創(chuàng)建FMDatabase對象
// 通過指定數(shù)據(jù)庫文件路徑來創(chuàng)建FMDatabase對象
+ (instancetype)databaseWithPath:(NSString*)inPath;
- (instancetype)initWithPath:(NSString*)inPath;
// path文件路徑
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
NSLog(@"數(shù)據(jù)庫打開失斘笳!");
}
// 關(guān)閉數(shù)據(jù)庫
// [db close];
文件路徑有三種情況(在FMDB文檔里有說明的)
1,具體的系統(tǒng)文件路徑,如果不存FMDatabase對象在會(huì)自動(dòng)創(chuàng)建
2,數(shù)據(jù)庫路徑為空字符串@"", 會(huì)在零食目錄創(chuàng)建一個(gè)空的數(shù)據(jù)庫,當(dāng)FMDatabase關(guān)閉連接時(shí),數(shù)據(jù)庫文件也會(huì)被刪除
3,nil,會(huì)創(chuàng)建一個(gè)內(nèi)存中臨時(shí)數(shù)據(jù)庫,當(dāng)FMDatabase關(guān)閉連接時(shí), 數(shù)據(jù)庫也會(huì)被銷毀.
執(zhí)行更新
在FMDB中妄迁,除查詢以外的所有操作寝蹈,都稱為“更新”create、drop登淘、insert箫老、update、delete等
// 下面這些方法在FMDatabase.h文件有詳細(xì)的說明,建議查看頭文件.
使用executeUpdate:方法執(zhí)行更新,sql和format是數(shù)據(jù)庫字符串
- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
// 示例
// 創(chuàng)表
NSString *creatTableSql = @"CREATE TABLE IF NOT EXISTS t_userTable (id integer PRIMARY KEY autoincrement, name text, price integer)";
[db executeUpdate:creatTableSql];
// 增加數(shù)據(jù)
[db executeUpdate:@"UPDATE t_shop SET price = ? WHERE name = ?;", @20, @"Jack"]
執(zhí)行查詢
查詢方法在FMDatabase.h文件中,返回的是FMResultSet結(jié)果集
常用的查詢方法,sql和format是數(shù)據(jù)庫字符串
- (FMResultSet *)executeQuery:(NSString*)sql, ...
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
// 示例
// 查詢數(shù)據(jù)
FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_shop"];
// 遍歷結(jié)果集
while ([rs next]) {
NSString *name = [rs stringForColumn:@"name"];
int price = [rs intForColumn:@"price"];
}
// FMDatabaseQueue提供了三個(gè)對象方法
//1. 同步隊(duì)列執(zhí)行數(shù)據(jù)庫操作黔州。
- (void)inDatabase:(void (^)(FMDatabase *db))block;
//2.使用事務(wù)進(jìn)行同步隊(duì)列執(zhí)行數(shù)據(jù)庫操作
- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
//3.使用遞延交易
- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
在項(xiàng)目中用FMDB做數(shù)據(jù)的存取的時(shí)候需要考慮到線程的安全問題,所以我在使用的時(shí)候是這樣用的
// 數(shù)據(jù)庫隊(duì)列
static FMDatabaseQueue *queue = nil;
if (!queue) {
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"fmdb.db"];
// 該方法會(huì)根據(jù)路徑去獲取一個(gè)隊(duì)列,如果路徑不存在會(huì)自動(dòng)創(chuàng)建一個(gè)數(shù)據(jù)庫
queue = [FMDatabaseQueue databaseQueueWithPath:path];
}
if (queue == nil) {
NSLog(@"創(chuàng)建隊(duì)列失敗");
return ;
}
// 創(chuàng)表
[queue inDatabase:^(FMDatabase *db) {
NSString *creatTableSql = @"CREATE TABLE IF NOT EXISTS t_userTable (id integer PRIMARY KEY autoincrement, uid integer, name text, timeStamp integer)";
[db executeUpdate:creatTableSql];
}];
// 添加數(shù)據(jù)
static int i = 0;
time_t now;
time_t timeStamp = time(&now);
i++;
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdateWithFormat:@"INSERT INTO t_userTable (uid, name, timeStamp) VALUES (%d, %@, %ld)", i, @"jack", timeStamp];
}];
// 查詢數(shù)據(jù)
[queue inDatabase:^(FMDatabase *db) {
NSString *query = [NSString stringWithFormat:@"SELECT * FROM t_userTable"];
FMResultSet *set = [db executeQuery:query];
while ([set next]) {
NSString *uid = [set stringForColumn:@"uid"];
NSString *name = [set stringForColumn:@"name"];
long int timeStamp = [set intForColumn:@"timeStamp"];
}
}];
// 修改數(shù)據(jù)
NSString *update = [NSString stringWithFormat:@"UPDATE t_userTable set uid = 100 where uid > 10"];
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:update];
}];
// 刪除數(shù)據(jù)
NSString *delete = [NSString stringWithFormat:@"DELETE FROM t_userTable where uid < %zd", 10];
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:delete];
}];
關(guān)于數(shù)據(jù)庫的詳細(xì)的知識,后期不忙了再補(bǔ)上.大神們?nèi)缬性敿?xì)見解,期望您