數據持久化

iOS中可以有四種持久化數據的方式:屬性列表、對象歸檔、SQLite3、和Core Data。


一、關於屬性列表的使用

iOS應用程序採用沙盒原理設計,每個應用程序都有自己的3個目錄(Documents,Library,tmp),互相之間不能訪問。

Documents存放應用程序的數據。

Library目錄下面還有Preferences和Caches目錄,Preferences目錄存放應用程序的使用偏好,Caches目錄與Documents很相似,可以存放應用程序的數據。

tmp目錄提供應用程序存儲臨時文件。


//獲得應用程序的Documents文件夾

NSArray* myPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

NSString* myDocPath = [myPaths objectAtIndex:0];

//獲取文件的完整路徑

NSString* filename = [myDocPath stringByAppendingPathComponent:@"properties.plist"];


//獲取tmp目錄

NSString* tempPath = NSTemporaryDirectory();

//獲取文件的完整路徑

NSString* tempFile = [tempPath stringByAppendingPathComponent:@"properties.plist"];


實例:

點擊save按鈕,將文本框的內容保存到Documents文件夾下得properties.plist文件中。

- (IBAction)save:(id)sender{

    NSArray* myPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMark,YES);

    NSString* myDocPath = [myPath objectAtIndex:0];

    NSString* filePath = [myDocPath stringByAppendingPathComponent:@"properties.plist"];

    NSMutableArray* data = [[[NSMutableArray alloc] init] autorelease];

    [data addObject:textField.text];

    [data writeToFile:filePath atomically:YES];

}

點擊load按鈕,將Documents文件夾下properties.plist文件的內容顯示到文本框中。

- (IBAction)load:(id)sender{

     NSArray* myPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMark,YES);

    NSString* myDocPath = [myPath objectAtIndex:0];

    NSString* filePath = [myDocPath stringByAppendingPathComponent:@"properties.plist"];

    if([[NSFileManager defaultManager] fileExistsAtPath:filePath]){

        NSMutableArray* data = [[[NSMutableArray alloc] initWithContentsOfFile:filePath] autorelease];

        textField.text = [data objectAtIndex:0];

    }

}


二、對象歸檔

“歸檔”是值另一種形式的序列化,對模型對象進行歸檔的技術可以輕鬆將複雜的對象寫入文件,然後再從中讀取它們,只要在類中實現的每個屬性都是基本數據類型(int或者float)或都是符合NSCoding協議的每個類的實例,你就可以對你的對象進行完整的歸檔。

  //實現NSCoding協議,有兩個方法:

- (void)encodeWithCoder:(NSCoder*)aCoder;//將對象寫入到文件中

- (id)initWithCoder:(NSCoder*)aDecoder;//文件中的數據讀入到對象中

  //實現NSCopying協議,有一個方法:

- (id)copyWithZone:(NSZone*)zone;//複製對象

實例:

創建一個Student類(遵循NSCoding、NSCopying協議),屬性值有studentId,studentName,studentClass

- (void)encodeWithCoder:(NSCoder*)aCoder{

    [aCoder encodeObject:studentId forKey:@"studentId"];

    [aCoder encodeObject:studentName forKey:@"studentName"];

    [aCoder encodeObject:studentClass forKey:@"studentClass"];

}

- (id)initWithCoder:(NSCoder*)aDecoder{

    self.studentId = [aDecoder decodeObjectForKey:@"studentId"];

    self.studentName = [aDecoder decodeObjectForKey:@"studentName"];

    self.studentClass = [aDecoder decodeObjectForKey:@"studentClass"];

    return self;

}

- (id)copyWithZone:(NSZone*)zone{

    Student* student = [Student allocWithZone:zone];

    student.studentId = self.studentId;

    student.studentName = self.studentName;

    student.studentClass = self.studentClass;

    return student;

}

然後在視圖控制器類中有三個文本框,名爲“_idText,_nameText,_classText"

點擊save按鈕,將三個文本框的值存入到文件中

- (IBAction)save:(id)sender{

    NSArray* myPaths = NSSearchPathDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMark,YES);

    NSString* myDocPath = [myPaths objectAtIndex:0];

    NSString* filename = [myDocPath stringByAppendingPathComponent:@"student.archive"];

    //以上是獲取文件的路徑及要使用的文件

    //聲明一個Student對象,將三個文本框的值賦給Student對象的三個屬性值

    Student* student = [[[Student alloc] init] autorelease];

    student.studentId = _idText.text;

    student.studentName = _nameText.text;

    student.studentClass = _classText.text;

    //將對象存儲到文件中需要使用NSKeyedArchiver對象,而創建NSKeyedArchiver對象,需要NSMutableData對象,把要存儲的對象存儲到data中,所以。。。

NSMutableData* theData = [NSMutableData data];

    NSKeyedArchiver* archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:theData] autorelease];

    [archiver encodeObject:student forKey:@"student"];

    [archiver finishEncoding];

    [theData writeToFile:filename atomically:YES];//將數據寫入到文件中

}


點擊load按鈕,把文件中的內容顯示到三個文本框中

- (IBAction)load:(id)sender{

    //先獲取文件的路徑 

    NSArray* myPaths = NSSearchPathDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMark,YES);

    NSString* myDocPath = [myPaths objectAtIndex:0];

    NSString* filename = [myDocPath stringByAppendingPathComponent:@"student.archive"];

    //把文件中的內容保存到NSData中

    NSData* theData = [NSData dataWithContentsOfFile:filename];

    //使用theData對象,來創建NSKeyedUnarchiver對象

    NSKeyedUnarchiver* unArchiver = [[[NSKeyedUnarchiver alloc] initForReadingWithData:theData] autorelease];

    //然後解檔,用Student對象接收

    Student* student = [unArchiver decodeObjectForKey:@"student"];

    //最後給三個文本框進行賦值

    _idText.text = student.studentId;

    _nameText.text = student.studentName;

    _classText.text = student.studentClass;

}


三、SQLite3(數據庫)

使用SQLite3的時候需要在framework框架下添加libsqlite3.dylib類庫。

包含頭文件import "sqlite3.h",定義一個數據庫指針sqlite3* db;

在Documents文件夾下創建數據庫:

NSArray* myPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMark,YES);

NSString* myDocPath = [myPaths objectAtIndex:0];

NSString* filename = [myDocPath stringByAppendingPathComponent:@"data.sqlite3"];

//打開數據庫sqlite3_open。

//創建數據庫表和執行SQL語句sqlite3_exec。

//釋放資源sqlite3_close。

//下面代碼是創建一個表格:

if(sqlite3_open([filename UTF8String],&db) != SQLITE_OK){

    //在sqlite3中的函數都是使用C字符串,[filename UTF8String]是將NSString類型的字符串轉換成C字符串。該函數返回SQLITE_OK,表明打開成功。

    sqlite3_close(db);

    NSAssert(NO,@"數據庫打開失敗");

}else{

    char* err;

    //創建一條sql語句,功能是建立一個表,表名是student,三列爲_idText,_nameText,_classText

    NSString* createSQL = [NSString stringWithFormat:@"create table if not exists %@(%@ TEXT primary key,%@ TEXT,%@ TEXT);",@"student",@"idText",@"_nameText",@"_classText"];

    if(sqlite3_exec(db,[createSQL UTF8String],NULL,NULL,&err) != SQLITE_OK){

        //sqlite_exec是執行任何不帶返回值的sql語句,第二個參數是要執行的sql語句,第三個參數要回調的函數,第四個參數是回調函數的參數,第五個參數是執行出錯的字符串。

        sqlite3_close(db);

        NSAssert(NO,@"建表失敗");//斷言函數,當斷言失敗時打印信息。

    }

    sqlite3_close(db);

}

/*

  預處理sql語句sqlite3_prepare_v2(1,2,3,4,5);

        第一個參數是sqlite3的指針,第二個參數是sql語句(c字符串),第三個參數是“-1”(代表是全部的sql字符串),第四個參數是sqlite3_stmt指針的地址,第五個參數是sql語句沒有被執行的部分語句。

  綁定參數sqlite3_bind_text(1,2,3,4,5);

        第一個參數是sqlite3_stmt的指針,第二個參數爲序號(從1開始),第三個參數是字符串值,第四個參數爲字符串的長度,第五個參數爲一個函數指針,SQLITE3執行完操作後回調此函數,通常用於釋放字符串佔用的內存。

  執行語句sqlite3_step(statement)

  釋放資源sqlite3_finalize和sqlite3_close

*/

//下面代碼是往表格中插入數據

當數據庫打開成功之後

    NSString* sqlStr = [NSString stringWithFormat:@"insert or replace into %@(%@,%@,%@) values(?,?,?)",@"student",@"_idText",@"_nameText",@"_classText"];

    sqlite3_stmt* statement;

    if(sqlite3_prepare_v2(db,[sqlStr UTF8String],-1,&statement,NULL) == SQLITE_OK){       //執行成功之後,開始綁定參數

sqlite3_bind_text(statement,1,[_idText.text UTF8String],-1,NULL);

sqlite3_bind_text(statement,2,[_nameText.text UTF8String],-1,NULL);

sqlite3_bind_text(statement,3,[_classText.text UTF8String],-1,NULL);

          //開始執行

        if(sqlite3_step(statement) != SQLITE_DONE){//判斷是否執行完成sql語句執行

    NSAssert(NO,@"插入失敗");

}

}

sqlite3_finalize(statement);//釋放資源

sqlite3_close(db);     //釋放資源


//下面代碼是把數據庫文件中的數據顯示到文本框上來

當打開數據庫成功之後

NSString* sqlStr = [NSString stringWithFormat:@"select %@,%@,%@ from %@ where %@ = ?",@"_idText",@"_nameText",@"_classText",@"student",@"_idText"];

    sqlite3_stmt* statement;

    //預處理過程

    if(sqlite3_prepare_v2(db,[sqlStr UTF8String],-1,&statement,NULL) == SQLITE_OK){

        //綁定參數

        sqlite3_bind_text(statement,1,"1000",-1,NULL);//這裏的“1000”是_idText的值

        //執行

        while(sqlite3_step(statement) == SQLITE_ROW){

//單步執行並判斷sql語句執行的狀態

            char* field1 = (char*)sqlite3_column_text(statement,0);

//sqlite3_column_text(statement,0) 取出字段值,第二個參數是列的順序,從0開始。

            NSString* field1Str = [[[NSString alloc] initWithUTF8String:field1] autorelease];

  _idText.text = field1Str;

  char* field2 = (char*)sqlite3_column_text(statement,1);

       NSString* field2Str = [[[NSString alloc] initWithUTF8String:field2] autorelease];

  _nameText.text = field2Str;

  char* field3 = (char*)sqlite3_column_text(statement,2);

  NSString* field3Str = [[[NSString alloc] initWithUTF8String:field3] autorelease];

  _classText.text = field3Str;

  }

    }

    sqlite3_finalize(statement);

    sqlite3_close(db);


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