iOS 數據存儲的幾種方式

在iOS開發過程中常用的本地化存儲有五種方式:

1.plist (XML屬性列表歸檔 NSArray\NSDictionary)

2.preference (偏好設置\NSUserDefaults) (本質還是通過plist來存儲數據,但是使用更加簡單,無需關注文件、文件夾路徑和名稱)

3.NSCoding (NSKeyedArchiver\NSKeyedUnarchiver)  (能把任何對象都直接保存成文件的方式)

4.SQLite3  (當非常大量的數據時候纔會使用)

5.Core Data (是對SQLite3的封裝,更加面向對象,效率沒有SQLite3高)

沙盒(sandbox):每個iOS應用都有自己的應用沙盒(應用沙盒就是應用的文件夾),與其他文件系統隔離。應用必須待在自己的沙盒裏,其他應用不能訪問該沙盒
應用沙盒的文件系統目錄,如下圖所示(假設應用的名稱叫Layer)

沙盒結構分析:
應用程序包:(上圖中的Layer)包含了所有的資源文件和可執行文件
Documents:保存應用運行時生成的需要持久化的數據,iTunes同步設備時會備份該目錄。例如,遊戲應用可將遊戲存檔保存在該目錄。保存相對重要的數據。

tmp:保存應用運行時所需的臨時數據,使用完畢後再將相應的文件從該目錄刪除。應用沒有運行時,系統也可能會清除該目錄下的文件。iTunes同步設備時不會備份該目錄。保存不重要的並且大的數據。

Library/Caches:保存應用運行時生成的需要持久化的數據,iTunes同步設備時不會備份該目錄。一般存儲體積大、不需要備份的非重要數據

Library/Preference:保存應用的所有偏好設置,iOS的Settings(設置)應用會在該目錄中查找應用的設置信息。iTunes同步設備時會備份該目錄。該目錄由系統管理, 無需我們來管理。通常用來存儲一些基本的軟件配置信息, 比如記住密碼、自動登錄等。

總結: 我們平時操作數據主要使用Documents目錄。

沙盒的目錄的獲取方式
沙盒根目錄的獲取:
NSString *home = NSHomeDirectory();
1.利用沙盒根目錄拼接”Documents“字符串:
//這種方式不建議使用,因爲如果新版本的操作系統可能會修改目錄的名稱
NSString *home = NSHomeDirectory();
NSString *documents = [home stringByAppendingPathComponent:@“Documents”];

2.利用NSSearchPathForDirectoriesInDomains函數
// NSUserDomainMask 代表從用戶文件夾下找
// YES 代表展開路徑中的波浪字符“~”
NSArray *array =  NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// 在iOS中,只有一個目錄跟傳入的參數匹配,所以這個集合裏面只有一個元素
NSString *documents = [array objectAtIndex:0];

常見沙盒目錄獲取方式:
tmp:NSString *tmp = NSTemporaryDirectory();
Library/Caches:(跟Documents類似的2種方法)
利用沙盒根目錄拼接”Caches”字符串
利用NSSearchPathForDirectoriesInDomains函數(將函數的第2個參數改爲:NSCachesDirectory即可)
Library/Preference:通過NSUserDefaults類存取該目錄下的設置信息


1、XML屬性列表(plist):(不能存儲基本數據類型只能存儲OC對象)

屬性列表是一種 xml格式的文件,拓展名爲plist,如果對象是(必須是OC對象,不能存儲基本數據類型)NSString、NSDictionary/NSArray、NSData 、NSNumber等類型,就可以使用writeToFile:atomically:方法直接將對象寫到屬性列表文件中,然後用dictionaryWithContentsOfFile讀取數據。

示例代碼如下:

//保存
- (IBAction)save {
        
        //1.獲取沙盒根路徑
        NSString *home = NSHomeDirectory();
        //2.document路徑
        NSString *docPath = [home stringByAppendingPathComponent:@"Documents"];
        //3.新建數據  數據一般只能存儲oc對象  字典也可以
        NSArray *data = @[@"jack",@"mack",@15];
        //4.寫數據
        NSString *filePath = [docPath stringByAppendingPathComponent:@"data.plist"];
        [data writeToFile:filePath atomically:YES];
}
//讀取
- (IBAction)read {
        
        //1.獲取沙盒根路徑
        NSString *home = NSHomeDirectory();
        //2.document路徑
        NSString *docPath = [home stringByAppendingPathComponent:@"Documents"];
        //3.文件路徑
        NSString *filePath = [docPath stringByAppendingPathComponent:@"data.plist"];
        //4.讀取數據
        NSArray *data = [NSArray arrayWithContentsOfFile:filePath];
        NSLog(@"%@",data);
}

//將一個NSDictionary對象歸檔到一個plist屬性列表中
// 將數據封裝成字典
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"母雞" forKey:@"name"];
[dict setObject:@"15013141314" forKey:@"phone"];
[dict setObject:@"27" forKey:@"age"];
// 將字典持久化到Documents/stu.plist文件中
[dict writeToFile:path atomically:YES];

//讀取屬性列表,恢復NSDictionary對象
// 讀取Documents/stu.plist的內容,實例化NSDictionary
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSLog(@"name:%@", [dict objectForKey:@"name"]);
NSLog(@"phone:%@", [dict objectForKey:@"phone"]);
NSLog(@"age:%@", [dict objectForKey:@"age"]);

2、prefrrence (偏好設置)

很多iOS應用都支持偏好設置,比如保存用戶名、密碼、字體大小等設置,iOS提供了一套標準的解決方案來爲應用加入偏好設置功能
每個應用都有個NSUserDefaults實例,通過它來存取偏好設置,比如,保存用戶名、字體大小、是否自動登錄等。

//存儲數據
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"itcast" forKey:@"username"];
[defaults setFloat:18.0f forKey:@"text_size"];
[defaults setBool:YES forKey:@“auto_login"];
//讀取上次保存的設置
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *username = [defaults stringForKey:@"username"];
float textSize = [defaults floatForKey:@"text_size"];
BOOL autoLogin = [defaults boolForKey:@"auto_login"];
[defaults synchornize];(立刻同步)
注意:UserDefaults設置數據時,不是立即寫入,而是根據時間戳定時地把緩存中的數據寫入本地磁盤。所以調用了set方法之後數據有可能還沒有寫入磁盤應用程序就終止了。出現以上問題,可以通過調用synchornize方法強制寫入

示例代碼如下:

//偏好設置數據存儲:(一般用來存儲軟件的配置,存儲在Library/Preferences中,不需要關注文件夾的路徑)

//存儲
- (IBAction)save {
           
        //1.利用NSUserDefaults,就能直接訪問軟件的偏好設置(Library/Preferences
       NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        //2.存儲數據
        [defaults setObject:@"jack" forKey:@"name"];
        [defaults setInteger:10 forKey:@"age"];
        [defaults setBool:YES forKey:@"Login"];
        //3.立刻同步
        [defaults synchronize];
}

//讀取
- (IBAction)read {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *name = [defaults objectForKey:@"name"];
        BOOL login = [defaults objectForKey:@"Login"];
        NSLog(@"%@-- %d",name,login);
}

3、NSCoding (NSKeyedArchiver\NSKeyedUnarchiver)

如果對象是NSString、NSDictionary、NSArray、NSData、NSNumber等類型,可以直接用NSKeyedArchiver進行歸檔和恢復
不是所有的對象(非OC對象)都可以直接用這種方法進行歸檔只有遵守了NSCoding協議的對象纔可以
NSCoding協議有2個方法:
encodeWithCoder:每次歸檔對象時,都會調用這個方法。一般在這個方法裏面指定如何歸檔對象中的每個實例變量,可以使用encodeObject:forKey:方法歸檔實例變量
initWithCoder:每次從文件中恢復(解碼)對象時,都會調用這個方法。一般在這個方法裏面指定如何解碼文件中的數據爲對象的實例變量,可以使用decodeObject:forKey方法解碼實例變量


示例代碼如下:

NSKeyedArchiver數據存儲,不僅可以用來存儲OC對象,也可以用來存儲非OC對象,以一個Person對象爲例:(想歸檔某個對象,這個對象一定要遵守NSCoding這個協議)
#import <Foundation/Foundation.h>
@interface TWPerson : NSObject <NSCoding>
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) int age;
@property (nonatomic,assign) double height;
@end

@implementation TWPerson
//將對象歸檔的時候調用(將對象寫入文件之前調用)
//在這個方法裏說清楚:1.哪些屬性需要存儲  2.怎樣存儲這些屬性
-(void)encodeWithCoder:(NSCoder *)enCoder
{
        //將_name屬性進行編碼(會將_name的值存進文件)
        [enCoder encodeObject:_name forKey:@"name"];
        [enCoder encodeInt:_age forKey:@"age"];
        [enCoder encodeDouble:_height forKey:@"height"];
    
}
//當從文件中解析對象時使用
//在這個方法說清楚: 1.那個屬性需要解析(讀取)  2.怎樣解析(讀取)這些屬性
- (id)initWithCoder:(NSCoder *)Decoder
{
    
        if (self = [super init]) {
                _name = [Decoder decodeObjectForKey:@"name"];
                _age = [Decoder decodeIntForKey:@"age"];
                _height = [Decoder decodeDoubleForKey:@"height"];
            }
        return self;
}
@end

//存儲數據
- (IBAction)save {
        TWPerson *p = [[TWPerson alloc]init];
        p.name = @"jack";
        p.age = 10;
        p.height = 1.82;
        NSString *path = @"/Users/wtw/Desktop/person.data";
        //歸檔
        [NSKeyedArchiver archiveRootObject:p toFile:path];
}
//讀取數據
- (IBAction)read {
        NSString *path = @"/Users/wtw/Desktop/person.data";
        //讀檔(反歸檔)
       TWPerson *p = [NSKeyedUnarchiver  unarchiveObjectWithFile:path];
        NSLog(@"%@ -- %f -- %d",p.name,p.height,p.age);
}
4、SQLite3
SQLite3 是一款開源的輕型的嵌入式關係型數據庫,可移植性好、易使用、內存開銷小,SQLite3 是無類型的,可以保存任何類型的數據到任意的字段中。

數據庫存儲數據的步驟:

》新建一個數據庫(DataBase)

》新建一張表(table)

》添加多個字段(column,列,屬性)

》添加多行記錄(row,每行存放多個字段對應的值)

SQL語句的分類:

數據定義語句:(DDL :Data Definition Language)

包括create drop 等操作。

在數據庫中創建新表或者刪除表(creat table 或 drop table)

數據庫操作語句: (DML : Data manipulation Language)

包括 insert 、update 、delete 等操作。

上面的3種操作分別用於添加、修改、刪除表中的數據

數據查詢語句 :(DQL : Data Query Language)

可以用於查詢獲得表中的數據

關鍵字select 是 DQL 用的最多的操作

其他DQL 常用的關鍵字有 where 、order by、group by 和 having 等。

創建表:

//創建表:
/*
 創建數據表
 CREATE TABLE '表名' (
 '字段1' 類型(INTEGER, REAL, TEXT, BLOB)
    NOT NULL    不允許爲空
    PRIMARY KEY    主鍵
    AUTOINCREMENT 自增長,
 '字段名2' 類型,
 ...
 )
*/
提示:可以從navicat先創建好表,複製粘貼,需要自己增加 IF NOT EXISTS

CREATE TABLE IF NOT EXISTS "T_Person" (
       "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
       "name" TEXT,
       "age" INTEGER,
       "heigth" REAL
       )
刪除表:

//刪除表
//DROP TABLE t_student;
DROP TABLE IF EXISTS t_student;
插入數據:

//插入命令:
INSERT INTO 表名
    (字段名1,字段名2…..)
    VALUES
    (值1,值2。。。。)
//注意:值和字段一定要一致
//提示:SQLite的字段屬性,只是給程序員看的,存什麼都行

INSERT INTO t_student
    (age, score, name)
    VALUES
    ('28', 100, 'zhangsan');
更新數據

//更新數據:
UPDATE  表名
    SET
    字段1 = ‘值1’  ,        //提示: 如果是字符串,需要使用單引號引起來
    字段2 = 值2 ,...
/*更新記錄的name*/
UPDATE t_student SET name = 'zhangsan';
//注意:如果更新時沒有指定更新哪一條記錄,那麼會更新所有的數據

刪除數據

//刪除指令:
//注意:刪除數據的時候,一定要設置條件
//如果條件不滿足,什麼也不會發生

DELETE  FROM  表名
    WHERE 主鍵 = 值;

//例如:
DELETE FROM t_student;
DELETE FROM t_student WHERE age < 50;

查詢數據

//查詢指令:
/* 分頁 */
SELECT * FROM t_student
ORDER BY id ASC LIMIT 30, 10;
/* 排序 */
SELECT * FROM t_student
WHERE score > 50
ORDER BY age DESC;
SELECT * FROM t_student
WHERE score < 50
ORDER BY age ASC , score DESC;
/* 計量 */
SELECT COUNT(*)
FROM t_student
WHERE age > 50;
/* 別名 */
SELECT name as myName, age as myAge, score as myScore
FROM t_student;
SELECT name myName, age myAge, score myScore
FROM t_student;
SELECT s.name myName, s.age myAge, s.score myScore
FROM t_student s
WHERE s.age > 50;
/* 查詢 */
SELECT name, age, score FROM t_student;
SELECT * FROM t_student;

數據庫的基本使用:

     @property (nonatomic, assign) sqlite3 *db;  
     /*
     1.創建數據庫
     2.創建表(指定字段)
     3.操作數據庫
     */
    /*
     第一個參數:是告訴系統數據庫文件在什麼地方.
     >如果文件不存在就會自動創建, 然後再打開
     >如果數據庫存在就會自動打開
     第二個參數:返回打開的數據庫對象
     */
    // 1.拼接數據庫地址
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    NSString *sqlFile = [path stringByAppendingPathComponent:@"student.sqlite"];
//    sqlite3 *db = NULL;
    // 2.打開數據庫
    int result = sqlite3_open(sqlFile.UTF8String, &_db);// [self db]
    // 3.判斷是否打開成功
    if (result == SQLITE_OK) {
        NSLog(@"打開成功");
        // 3.1創建表
        /*
         第一個參數: 需要執行SQL語句的數據庫對象
         第二個參數: 需要執行的SQL語句
         第三個參數: 回調函數
         第四個參數: 第三個參數的參數
         第五個參數: 接收錯誤信息
         */
        NSString *sql = @"CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT , name TEXT, age INTEGER, score REAL);";
        result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
        if (result == SQLITE_OK) {
            NSLog(@"創建表成功");
        }else
        {
            NSLog(@"創建表失敗");
        }
    }else
    {
        NSLog(@"打開失敗");
    }
- (IBAction)insertClick:(id)sender {
    
    NSString *sql = @"INSERT INTO t_student(age, score, name) VALUES ('28', 100, 'jonathan');";
    int result =  sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
    if (result == SQLITE_OK) {
        NSLog(@"插入成功");
    }
}

- (IBAction)updateClick:(id)sender {
    NSString *sql = @"UPDATE t_student SET name = 'XXX';";
    int result =  sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
    if (result == SQLITE_OK) {
        NSLog(@"修改成功");
    }
}

- (IBAction)deleteClick:(id)sender {
    NSString *sql = @"DELETE FROM t_student WHERE id = 1; ";
    int result =  sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
    if (result == SQLITE_OK) {
        NSLog(@"刪除成功");
    }6
}

- (IBAction)selectClick:(id)sender {
    /*
     sqlite3操作中, 所有DML語句都是使用sqlite3_exec函數執行SQL語句即可,
     但是如果是需要查詢數據庫, 不能使用sqlite3_exec, 因爲它並沒有返回查詢到得結果發給我們
     */
    /*
    NSString *sql = @"SELECT * FROM t_student;";
    int result =  sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
    if (result == SQLITE_OK) {
        NSLog(@"查詢成功");
    }
     */
    // 1.準備查詢
    /*
     第一個參數:需要執行SQL語句的數據庫
     第二個參數:需要執行的SQL語句
     第三個參數: 告訴系統SQL語句的長度, 如果傳入一個小於0的數, 系統會自動計算
     第四個參數:結果集, 裏面存放所有查詢到的數據(不嚴謹)
     */
    NSString *sql = @"SELECT * FROM t_student;";
    sqlite3_stmt *stemt = NULL;
    sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stemt, NULL);
    // 2.判斷有沒有查詢結果
//    int result = sqlite3_step(stemt);
//    if (result == SQLITE_ROW) {
    while (sqlite3_step(stemt) == SQLITE_ROW) {
//        NSLog(@"查詢到了數據");
        // 3.取出查詢到得結果
        const unsigned char *name = sqlite3_column_text(stemt, 1);
        int age = sqlite3_column_int(stemt, 2);
        double score = sqlite3_column_double(stemt, 3);
        NSLog(@"%s %d %f", name, age, score);
    }
}

數據庫的基本的封裝

@interface SQLManager : NSObject

+ (instancetype)shareManage;
//插入新數據
- (BOOL)insertStudent:(HMStudent *)student;
//刪除數據
- (BOOL)deleteWithStudent:(HMStudent *)student;
//更新數據
- (BOOL)updateWithStudent:(HMStudent *)student;
//查詢數據
- (NSArray *)query;
@end
#import "SQLManager.h"
#import <sqlite3.h>

@implementation SQLManager

static SQLManager *_instance;
+ (instancetype)shareManage
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[SQLManager alloc] init];
    });
    return _instance;
}

sqlite3 *_db;
+ (void)initialize
{
    // 1.拼接數據庫地址
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    NSString *sqlFile = [path stringByAppendingPathComponent:@"student.sqlite"];
    // 2.打開數據庫
    int result = sqlite3_open(sqlFile.UTF8String, &_db);// [self db]
    // 3.判斷是否打開成功
    if (result == SQLITE_OK) {
        NSLog(@"打開成功");
        // 3.1創建表
        NSString *sql = @"CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT , name TEXT, age INTEGER, score REAL);";
        result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
    }
}

- (BOOL)insertStudent:(HMStudent *)student
{
    NSString *sql = [NSString stringWithFormat: @"INSERT INTO t_student(age, score, name) VALUES (%d, %f, '%@');", student.age, student.score, student.name];
    int result =  sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
    if (result == SQLITE_OK) {
        return YES;
    }
    return NO;
}
- (BOOL)deleteWithStudent:(HMStudent *)student
{
    NSString *sql = [NSString stringWithFormat:@"DELETE FROM t_student WHERE id = %d;",  student.ID];
    int result =  sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
    if (result == SQLITE_OK) {
        return YES;
    }
    return NO;
}
- (BOOL)updateWithStudent:(HMStudent *)student
{
    
    NSString *sql = [NSString stringWithFormat:@"UPDATE t_student SET name = '%@';", student.name];
    int result =  sqlite3_exec(_db, sql.UTF8String, NULL, NULL, NULL);
    if (result == SQLITE_OK) {
        return YES;
    }
    return NO;
}
- (NSArray *)query
{
    NSString *sql = @"SELECT * FROM t_student;";
    sqlite3_stmt *stemt = NULL;
    sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stemt, NULL);
    // 2.判斷有沒有查詢結果
    NSMutableArray *arrM = [NSMutableArray array];
    while (sqlite3_step(stemt) == SQLITE_ROW) {
        // 3.取出查詢到得結果
        const unsigned char *name = sqlite3_column_text(stemt, 1);
        int age = sqlite3_column_int(stemt, 2);
        double score = sqlite3_column_double(stemt, 3);
        HMStudent *stu = [[HMStudent alloc] init];
        stu.name = [NSString stringWithUTF8String:name];
        stu.age = age;
        stu.score = score;
        [arrM addObject:stu];
    }
    return arrM;
}
@end

FMDB的基本使用:

以OC的方式封裝了SQLite的C語言API.

優點是:

使用起來更加面向對象,省去麻煩冗餘的C語言的代碼,對比蘋果的Core Data 框架,更加的輕量級和靈活,提供了多線程安全的數據庫操作方法,有效防止數據混亂。

FMDB有三個三個主要的類:

FMDataBase :一個FMDataBase 對象就代表一個單獨的DataBase數據庫,用來執行SQL語句。

FMResultSet: 使用FMResultSet執行查詢後的結果集。

FMDataBaseQueue: 用於多線程執行多個查詢或者更新,他是線程安全的。

@property (nonatomic, strong)  FMDatabase *db;
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    /*
     1.創建數據庫
     2.創建表
     3.操作
     */
    // 1.拼接數據庫地址
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    NSString *sqlFile = [path stringByAppendingPathComponent:@"student.sqlite"];
    //該方法接收一個路徑, 它會根據地址創建一個數據庫, 如果不存在就會自動創建
    FMDatabase *db = [FMDatabase databaseWithPath:sqlFile];
    self.db = db;
    if([db open]){
        // 2.創建表
        NSString *sql = @"CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT , name TEXT, age INTEGER, score REAL);";

        // 注意: 在FMDB中除了查詢以外的操作都稱之爲更新
        if([db executeUpdate:sql]){
            NSLog(@"創建表成功");
        }
    }
}
- (IBAction)insertClick:(id)sender
{  NSString *sql = @"INSERT INTO t_student(age, score, name) VALUES ('28', 100, 'jonathan');";
    if([self.db executeUpdate:sql])
    {
        NSLog(@"插入成功");
    }
}
- (IBAction)selectClick:(id)sender
{
    NSString *sql = @"SELECT * FROM t_student;";
    // 查詢數據, 會將所有查詢到得數據, 放到results中
    FMResultSet *results = [self.db executeQuery:sql];
    // 從results中獲取數據
    while ([results next]) {
        NSString *name = [results stringForColumn:@"name"];
        int age = [results intForColumn:@"age"];
        double score = [results doubleForColumn:@"score"];
        NSLog(@"%@ %d %f", name, age, score);
    }
}

FMDataBaseQueue:

@property (nonatomic, strong) FMDatabaseQueue *dbQueue;
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 1.拼接數據庫地址
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    NSString *sqlFile = [path stringByAppendingPathComponent:@"student.sqlite"];
    // 創建一個數據庫隊列
    FMDatabaseQueue *dbQueue = [FMDatabaseQueue databaseQueueWithPath:sqlFile];
    self.dbQueue = dbQueue;
    //只要調用dbQueue的inDatabase方法, 系統就會傳遞一個已經打開並且線程安全的數據庫給我們
    [dbQueue inDatabase:^(FMDatabase *db) {
        // 2.創建表
        NSString *sql = @"CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT , name TEXT, age INTEGER, score REAL);";
        
        // 注意: 在FMDB中除了查詢以外的操作都稱之爲更新
        if([db executeUpdate:sql]){
            NSLog(@"創建表成功");
        }
    }];
}
- (IBAction)insertClick:(id)sender
{
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = @"INSERT INTO t_student(age, score, name) VALUES ('28', 100, 'jonathan');";
        if([db executeUpdate:sql])
        {
            NSLog(@"插入成功");
        }
    }];
}
- (IBAction)selectClick:(id)sender
{
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = @"SELECT * FROM t_student;";
        // 查詢數據, 會將所有查詢到得數據, 放到results中
        FMResultSet *results = [db executeQuery:sql];
        // 從results中獲取數據
        while ([results next]) {
            NSString *name = [results stringForColumn:@"name"];
            int age = [results intForColumn:@"age"];
            double score = [results doubleForColumn:@"score"];
            NSLog(@"%@ %d %f", name, age, score);
        }
    }];
}
@end

事務:可以將多條SQL數據綁定在一起,要麼一起執行成功要麼一起執行失敗。

CoreData:

Core Data框架提供了對象-關係映射(ORM)的功能,即能夠將OC對象轉化成數據,保存在SQLite3數據庫文件中,也能夠將保存在數據庫中的數據還原成OC對象。在此數據操作期間,不需要編寫任何SQL語句。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章