接着上一篇应用程序,继续往下写内容
本篇文章,看标题内容,就知道是在上篇项目的基础上增加SQLite3数据库方面的操作
所以UI无需任何更改。这里是链接
因为没找到十分合适又全面的博客文档,所以就自己写一篇吧,看客们就不要纠结我的文学水平了。
首先,在我们的项目中,添加添加SQLite3支持库
在添加SQLite3的支持库时,需要注意,我们选择libsqlite3.dylib,这是一个数据库的索引,动态的指向最新的SQLite3的动态库。
然后我们回到ToDoListTableViewController.h文件,在这里引入sqlite3.h。
我将所有的数据库的操作,都放在了ToDoListTableViewController.m里。
先定义两个私有变量,直接将代码片段截取出来。
<span style="font-family:Comic Sans MS;font-size:24px;">@interface ToDoListTableViewController ()
//定义私有变量属性
@property NSMutableArray *toDoItems;
@property sqlite3 *database;
@property (copy, nonatomic) NSString *databaseFilePath;
@end
@implementation ToDoListTableViewController
@synthesize database;
@synthesize databaseFilePath;
</span>
单独定义一个获取数据库路径的方法,以便实现必要的时候的代码重用
<span style="font-family:Comic Sans MS;font-size:24px;">#pragma 获取数据库路径
- (void)initialDatabaseFilePath {
NSArray *dir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [dir objectAtIndex:0];
databaseFilePath = [documentDir stringByAppendingPathComponent:@"database.sqlite3"];
NSLog(@"databaseFilePath:%@", databaseFilePath);
}
</span>
刚开始做的时候,在这里入坑了,调试了半天,才发现获取目录参数写错了,各位也需要注意。
定义一个打开或创建数据库的方法,当然也是为了代码重用
<span style="font-family:Comic Sans MS;font-size:24px;">#pragma 打开或创建数据库
- (int)openOrCreate {
int i = sqlite3_open([self.databaseFilePath UTF8String], &database);
if (i == SQLITE_OK) {
NSLog(@"数据库打开成功");
} else {
NSLog(@"数据库打开失败");
}
return i;
}
</span>
定义一个创建数据库表的方法
<span style="font-family:Comic Sans MS;font-size:24px;">#pragma 创建数据库表
- (void)createTableNotExists {
if ([self openOrCreate] != SQLITE_OK) {
return;
}
NSString *createSQL = @"create table if not exists ToDoItem(id Integer primary key autoincrement, itemName text)";
char *errmsg;
int i = sqlite3_exec(database, [createSQL UTF8String], NULL, NULL, &errmsg);
if (i == SQLITE_OK) {
NSLog(@"数据库表创建成功");
} else {
NSLog(@"数据库表创建失败");
}
// 必须要记得关闭数据库操作
sqlite3_close(database);
}
</span>
以上是SQLite3操作中的初始化操作。
然后就是对数据库的增删改查操作了,本篇文章只给出增删查操作的方法,修改自己完善。
定义一个查询数据库表中数据的方法,并将获取到的数据封装到数组对象中去
<span style="font-family:Comic Sans MS;font-size:24px;">#pragma 查询数据库表中数据
- (void)querySQLite {
if ([self openOrCreate] != SQLITE_OK) {
return;
}
sqlite3_stmt *stmt;
NSString *querySQL = @"select itemName from ToDoItem";
int i = sqlite3_prepare_v2(database, [querySQL UTF8String], -1, &stmt, nil);
if (i == SQLITE_OK) {
// 依次读取数据表ToDoItem中每行的内容
while (sqlite3_step(stmt) == SQLITE_ROW) {
char *itemName = (char *)sqlite3_column_text(stmt, 0);
ToDoItem *item = [[ToDoItem alloc] init];
item.itemName = [[NSString alloc] initWithUTF8String:itemName];
[self.toDoItems addObject:item];
}
// 释放预处理资源
sqlite3_finalize(stmt);
}
// 关闭数据库连接
sqlite3_close(database);
}
</span>
定义一个新增数据的方法,将数据保存到数据库表中,此处使用占位符形式的操作,代码比之sqlite_exec();方法要稍微多点。
<span style="font-family:Comic Sans MS;font-size:24px;">#pragma 新增数据库表数据
- (void)insertSQLite:(ToDoItem *)toDoItem {
if ([self openOrCreate] != SQLITE_OK) {
return;
}
sqlite3_stmt *stmt;
NSString *insertSQL = @"insert into ToDoItem(itemName) values(?)";
int i = sqlite3_prepare_v2(database, [insertSQL UTF8String], -1, &stmt, nil);
if (i == SQLITE_OK) {
// 未预处理语句中的占位符绑定数据
sqlite3_bind_text(stmt, 1, [toDoItem.itemName UTF8String], -1, SQLITE_TRANSIENT);
// 执行插入语句
i = sqlite3_step(stmt);
// 释放预处理资源
sqlite3_finalize(stmt);
if (i == SQLITE_OK) {
NSLog(@"数据新增成功");
} else if (i == SQLITE_ERROR) {
NSLog(@"数据新增失败");
} else {
NSLog(@"数据库新增返回值:i = %d", i);
}
}
sqlite3_close(database);
}
</span>
这里遇到的问题是,新增操作的返回值,一开始只判断了SQLITE_OK后,直接else打印数据新增失败,导致控制台信息提示一直失败,悲剧。
现在修改viewDidLoad方法的内容
<span style="font-family:Comic Sans MS;font-size:24px;">- (void)viewDidLoad {
[super viewDidLoad];
[self initialDatabaseFilePath];
[self createTableNotExists];
self.toDoItems = [[NSMutableArray alloc] init];
// [self loadInitialData];
[self querySQLite];
}
</span>
修改unwindAddBack:方法,该方法是之前的unwindToList:方法,将方法名修改的更为形象
<span style="font-family:Comic Sans MS;font-size:24px;">- (void)unwindAddBack:(UIStoryboardSegue *)segue {
AddToDoItemViewController *controller = [segue sourceViewController];
ToDoItem *item = controller.toDoItem;
if (item) {
// 这里添加保存数据的方法
[self insertSQLite:item];
[self.toDoItems addObject:item];
[self.tableView reloadData];
}
}
</span>
如此在原来项目的基础上增加SQLite3的操作已经完成了,但是说实话,没用ORM框架,这个样子写代码实在太累了,今后找一个ORM框架给大家推荐一下。
以下是ObjectiveC中提供的SQLite3数据库操作函数介绍:
sqlite3_open(), 打开数据库
sqlite3_exec(), 执行非查询的sql语句
sqlite3_prepare(), 准备sql语句,执行select语句或者要使用parameter bind时,用这个函数(封装了sqlite3_exec).
Sqlite3_step(), 在调用sqlite3_prepare后,使用这个函数在记录集中移动。
sqlite3_finalize(),释放预处理语句资源
Sqlite3_close(), 关闭数据库文件
sqlite3_column_text(), 取text类型的数据。
sqlite3_column_blob(),取blob类型的数据
sqlite3_column_int(), 取int类型的数据
//使用预处理语句时的绑定参数函数
sqlite3_bind_int(stmt, 1, 1);
sqlite3_bind_text(stmt, 2, [title UTF8String], -1, SQLITE_TRANSIENT);
再给个哥们的SQLite3操作链接,看了他得文章,突然发现,我的博客还是可以看得,幸福果然都是比出来的: