您的位置:首页 > 数据库

盲人摸象——iOS简单应用ToDoList之sqlite数据本地化

2015-10-25 19:42 387 查看
最近花两天学习sqlite的简单应用,加到ToDolist中,然后搬运到github上面。

github 地址:

git@github.com:RootChen/ToDoList.git

设置文件路径

sqlite实现数据增删查改,存储在本地。那么存储在本地哪里呢?这就需要我们设置文件路径了:

- (NSString *)filePath {
NSString *filePath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@",kFilename];
return filePath;
}


这里设置的是一个相对路径,sqlite的表数据就存储在这个路径里。

创建表

设置好文件相对路径之后我们要进行sqlite的基本操作,第一步就是创建表:

- (void)createTable:(NSString *)sql {
sqlite3 *sqlite = nil;
//打开数据库
if (sqlite3_open([self.filePath UTF8String], &sqlite) != SQLITE_OK) {
NSLog(@"打开数据库失败");
sqlite3_close(sqlite);
return;
}

//执行创建表SQL语句
char *errmsg = nil;
if (sqlite3_exec(sqlite, [sql UTF8String], NULL, NULL, &errmsg) != SQLITE_OK) {
NSLog(@"创建表失败:%s",errmsg);
sqlite3_close(sqlite);
}
NSLog(@"创建表成功");
//关闭数据库
sqlite3_close(sqlite);

}


这个方法的输入参数是 NSString 类型的 sql,是指传入一句sql语句,根据 ToDOList 的每一项任务数据包含的内容:任务内容、任务标记、任务创建时间,我们这样调用 - (void)createTable:(NSString *)sql 方法:

- (void)createTable {
NSString *sql = @"CREATE TABLE IF NOT EXISTS Task (content TEXT,isMark TEXT,date TEXT primary key);";
[self createTable:sql];
}


可以把任务创建时间当做任务数据的 id,因为每一项任务的创建时间是唯一的。

sqlite的操作抽象出两个类

创建之后会有插入(增)、删除、查找、修改数据的操作,跟创建操作有一个共同之处,就是有 sqlite对应的基本操作的方法,调用方法时插入相关的 sql 语句,所以上述的 - (void)createTable:(NSString *)sql 方法连同增删改查的基本操作我们可以写在一个类 BaseDB中,可以在其他工程中重用,而调用基本操作的方法与业务数据相关,不具备好的重用性,所以将 - (void)createTable等方法写在类 TaskDb 中。

表数据处理的基本操作

/**
* 接口描述:插入数据、删除数据、修改数据
* 参数:  sql: SQL语句
* 返回值:是否执行成功
*
*/
- (BOOL)dealData:(NSString *)sql paramsarray:(NSArray *)params {
sqlite3 *sqlite = nil;
sqlite3_stmt *stmt = nil;

//打开数据库
if (sqlite3_open([self.filePath UTF8String], &sqlite) != SQLITE_OK) {
NSLog(@"打开数据库失败");
sqlite3_close(sqlite);
return NO;
}

//编译SQL语句
if (sqlite3_prepare_v2(sqlite, [sql UTF8String], -1, &stmt, NULL) != SQLITE_OK) {
NSLog(@"SQL语句编译失败");
sqlite3_close(sqlite);
return NO;
}

//绑定数据
for (int i=0; i<params.count; i++) {
NSString *value = [params objectAtIndex:i];
sqlite3_bind_text(stmt, i+1, [value UTF8String], -1, NULL);
}

//执行SQL语句
if(sqlite3_step(stmt) == SQLITE_ERROR) {
NSLog(@"SQL语句执行失败");
sqlite3_close(sqlite);
return NO;
}

//关闭数据库
sqlite3_finalize(stmt);
sqlite3_close(sqlite);

return YES;
}


添加、删除、修改都是调用了- (BOOL)dealData:(NSString )sql paramsarray:(NSArray )params方法:

//增加一个任务
- (BOOL)addTask:(Task *)task {
NSString *sql = @"INSERT INTO Task (content,isMark,date) VALUES (?,?,?)";

NSArray *params = [NSArray arrayWithObjects:task.content,
[NSString stringWithFormat: @"%d",task.isMark],
[NSString stringWithFormat:@"%@", task.date], nil];

return [self dealData:sql paramsarray:params];
}
//删除一个任务
- (BOOL)deleteTask:(Task *)task {
NSString *sql = [NSString stringWithFormat:@"DELETE FROM Task WHERE date = '%@'", [NSString stringWithFormat:@"%@", task.date]];

NSArray *params = [NSArray arrayWithObjects:task.content,
[NSString stringWithFormat: @"%d",task.isMark],
[NSString stringWithFormat:@"%@", task.date], nil];

return [self dealData:sql paramsarray:params];
}
//更新一个任务的标记状态
- (BOOL)updateTask:(Task *)task {
NSString *sql = [NSString stringWithFormat:@"UPDATE Task SET isMark = '%@' WHERE date = '%@' ",[NSString stringWithFormat: @"%d",task.isMark], [NSString stringWithFormat:@"%@", task.date]];
NSArray *params = [NSArray arrayWithObjects:task.content,
[NSString stringWithFormat: @"%d",task.isMark],
[NSString stringWithFormat:@"%@", task.date], nil];

return [self dealData:sql paramsarray:params];
}


一个删除导致添加有误的bug

BaseDB 这个类是无限互联3G学院的代码,对我等小白而言实在是赞,直接调用,上手容易。读懂代码以后,在BaseDB中单步调试,可以解决数据被覆盖等常见bug。

比如在删除一个任务的方法 - (BOOL)deleteTask:(Task *)task中,sql 语句 :

NSString *sql = [NSString stringWithFormat:@"DELETE FROM Task WHERE date = '%@'", [NSString stringWithFormat:@"%@", task.date]];


如果 @”DELETE FROM Task WHERE date = ‘%@’” 写成 @”DELETE FROM Task WHERE content = ‘%@’” ,那么你就无法添加多条内容相同的任务了,新建的任务会覆盖之前已经有的但是内容与它相同的任务。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: