转载请注明出处,原文网址:http://blog.csdn.net/m_changgong/article/details/8284135 作者:张燕广
实现的功能:1)演示使用sqlite3持久化数据。
关键词:数据持久化 sqlite3 数据库
1、将上一篇iPhone开发【二十二】数据持久化总结之第3篇归档(NSKeyedArchiver、NSKeyedUnarchiver)的工程拷贝一份,名称修改为Persistence-sqlite,工程结构如下:
Person类已经没用了,可以删掉。
2、为工程添加sqlite3的库libsqlite3.dylib,如下图所示:
3、主要修改了ViewController类,ViewController.h如下:
#define kFileName @"archive"
#define kDataKey @"Data"
#define kSqliteFileName @"data.db3"
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property(nonatomic,retain)IBOutlet UITextField *name;
@property(nonatomic,retain)IBOutlet UITextField *gender;
@property(nonatomic,retain)IBOutlet UITextField *age;
@property(nonatomic,retain)IBOutlet UITextField *education;
-(NSString *)dataFilePath;
-(void)applicationWillResignActive:(NSNotification *)nofication;
@end
ViewController.m如下:
#import "ViewController.h"
#import "Person.h"
#import <sqlite3.h>
@implementation ViewController
@synthesize name,gender,age,education;
-(NSString *)dataFilePath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//return [documentsDirectory stringByAppendingPathComponent:kFileName];
return [documentsDirectory stringByAppendingPathComponent:kSqliteFileName];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
// Do any additional setup after loading the view, typically from a nib.
NSString *filePath = [self dataFilePath];
NSLog(@"filePath=%@",filePath);
if([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
//属性列表
/*
NSArray *array = [[NSArray alloc]initWithContentsOfFile:filePath];
name.text = [array objectAtIndex:0];
gender.text = [array objectAtIndex:1];
age.text = [array objectAtIndex:2];
education.text = [array objectAtIndex:3];
[array release];*/
//归档
/*
NSData *data = [[NSMutableData alloc]initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
Person *person = [unarchiver decodeObjectForKey:kDataKey];
[unarchiver finishDecoding];
name.text = person.name;
gender.text = person.gender;
age.text = person.age;
education.text = person.education;
[unarchiver release];
[data release];*/
//sqlite3
sqlite3 *database;
//打开数据库
if(sqlite3_open([filePath UTF8String], &database)!=SQLITE_OK){//备注1
//数据库打开失败,关闭数据库
sqlite3_close(database);
NSAssert(0,@"打开数据库失败");
}
char* errorMsg;
NSString *createSQL = @"CREATE TABLE IF NOT EXISTS PERSON (name TEXT PRIMARY KEY,gender TEXT,age TEXT,education TEXT);";
//创建表
if(sqlite3_exec(database, [createSQL UTF8String], NULL, NULL, &errorMsg)!=SQLITE_OK){//备注2
//创建表失败,关闭数据库
sqlite3_close(database);
NSAssert1(0, @"创建表失败:%s", errorMsg);
}
//查询表
NSString *querySQL = @"SELECT name,gender,age,education FROM PERSON ORDER BY name";
//执行查询,遍历查询结果
sqlite3_stmt *statment;
if(sqlite3_prepare_v2(database, [querySQL UTF8String], -1, &statment, nil) == SQLITE_OK){//备注3
//查询成功,执行遍历操作
while(sqlite3_step(statment) == SQLITE_ROW){//备注4
const char* pName = (char*)sqlite3_column_text(statment, 0);//备注5
if(pName!=NULL){
self.name.text = [[NSString alloc]initWithUTF8String:pName];
}
char* pGender = (char*)sqlite3_column_text(statment, 1);
if(pGender!=NULL){
self.gender.text = [[NSString alloc]initWithUTF8String:pGender];
}
char* pAge = (char*)sqlite3_column_text(statment, 2);
if(pAge!=NULL){
self.age.text = [[NSString alloc]initWithUTF8String:pAge];
}
char* pEducation = (char*)sqlite3_column_text(statment, 3);
if(pEducation!=NULL){
self.education.text = [[NSString alloc]initWithUTF8String:pEducation];
}
}
sqlite3_finalize(statment);//备注6
}
//关闭数据库
sqlite3_close(database);//备注7
}
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:app];
[super viewDidLoad];
}
-(void)applicationWillResignActive:(NSNotification *)nofication{
//属性列表
/*
NSMutableArray *array = [[NSMutableArray alloc]init];
[array addObject:name.text];
[array addObject:gender.text];
[array addObject:age.text];
[array addObject:education.text];
[array writeToFile:[self dataFilePath] atomically:YES];
[array release];*/
//归档
/*
Person *person = [[Person alloc]init];
person.name = name.text;
person.gender = gender.text;
person.age = age.text;
person.education = education.text;
NSMutableData *data = [[NSMutableData alloc]init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archiver encodeObject:person forKey:kDataKey];
[archiver finishEncoding];
[data writeToFile:[self dataFilePath] atomically:YES];
[person release];
[archiver release];
[data release];*/
//sqlite3
sqlite3 *database;
//打开数据库
if(sqlite3_open([[self dataFilePath] UTF8String], &database)!=SQLITE_OK){
//数据库打开失败,关闭数据库
sqlite3_close(database);
NSAssert(0,@"打开数据库失败");
}
char* errorMsg;
NSString *updateSQL = @"INSERT OR REPLACE INTO PERSON(name,gender,age,education) VALUES(?,?,?,?);";
//执行插入或更新操作
sqlite3_stmt *statment;
if(sqlite3_prepare_v2(database, [updateSQL UTF8String], -1, &statment, nil) == SQLITE_OK){
//绑定变量
sqlite3_bind_text(statment, 1, [self.name.text UTF8String], -1, NULL);//备注8
sqlite3_bind_text(statment, 2, [self.gender.text UTF8String], -1, NULL);
sqlite3_bind_text(statment, 3, [self.age.text UTF8String], -1, NULL);
sqlite3_bind_text(statment, 4, [self.education.text UTF8String], -1, NULL);
}
if(sqlite3_step(statment)!=SQLITE_DONE){
NSAssert1(0, @"更新表失败:%s", errorMsg);
}
sqlite3_finalize(statment);
//关闭数据库
sqlite3_close(database);
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.name = nil;
self.gender = nil;
self.age = nil;
self.education = nil;
}
-(void)dealloc{
[name release];
[gender release];
[age release];
[education release];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
@end
代码解释:
备注1:sqlite3_open():打开数据库
在操作数据库之前,首先要打开数据库。
这个函数打开一个sqlite数据库文件的连接并且返回一个数据库连接对象。
第1个参数:数据文件路径必须用C风格字符串(不能用NSString),[filePath UTF8String]将filePath转换为C风格字符串。
第2个参数:是返回的数据库连接对象。
这个过程销毁前面被sqlite3_prepare创建的准备语句,每个准备语句都必须使用这个函数去销毁以防止内存泄露。
在空指针上调用这个函数没有什么影响,同时可以在准备语句的生命周期的任一时刻调用这个函数:在语句被执行前,一次或多次调用
sqlite_reset之后,或者在sqlite3_step任何调用之后。
备注7:sqlite3_close()
关闭前面使用sqlite3_open打开的数据库连接,任何与这个连接相关的准备语句必须在调用这个关闭函数之前被释放掉。
备注8:sqlite3_bind_text()
第1个参数:指向在sqlite3_prepare_v2()调用中使用的sqlite3_stme。
第2个参数:所绑定的变量的索引(sql语句中第一个问号的索引),需要注意的是:第一个问号的索引是1,而不是0。
第3个参数:只有少数绑定函数,比如用于绑定文本或二进制数据的绑定函数,这个参数用来设定传递数据的长度。对于C字符串,可以传递-1来代替字符串的长度,意思是要是要使用整个字符串。
第4个参数:回调函数,一般用于在语句执行后做内存清理相关的工作。可以设置为NULL。4、数据库文件的保存位置是: /Users/duobianxing/Library/Application Support/iPhone Simulator/5.0/Applications/CC47C118-7FE7-4718-A4AA-635FBCC36AED/Documents/data.db3