数据持久化

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);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值