【转】iOS开发24:使用SQLite3存储和读取数据
转自:http://my.oschina.net/plumsoft/blog/57626
SQLite3是嵌入在iOS中的关系型数据库,对于存储大规模的数据很有效。SQLite3使得不必将每个对象都加到内存中。
基本操作:
(1)打开或者创建数据库
sqlite3 *database;
int result = sqlite3_open("/path/databaseFile", &database);
如果/path/databaseFile不存在,则创建它,否则打开它。如果result的值是SQLITE_OK,则表明我们的操作成功。
注意上述语句中数据库文件的地址字符串前面没有@字符,它是一个C字符串。将NSString字符串转成C字符串的方法是:
const char *cString = [nsString UTF8String];
(2)关闭数据库
sqlite3_close(database);
(3)创建一个表格
char *errorMsg;
const char *createSQL = "CREATE TABLE IF NOT EXISTS PEOPLE (ID INTEGER PRIMARY KEY AUTOINCREMENT, FIELD_DATA TEXT)";
int result = sqlite3_exec(database, createSQL, NULL, NULL, &errorMsg);
执行之后,如果result的值是SQLITE_OK,则表明执行成功;否则,错误信息存储在errorMsg中。
sqlite3_exec这个方法可以执行那些没有返回结果的操作,例如创建、插入、删除等。
(4)查询操作
NSString *query = @"SELECT ID, FIELD_DATA FROM FIELDS ORDER BY ROW";
sqlite3_stmt *statement;
int result = sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil);
如果result的值是SQLITE_OK,则表明准备好statement,接下来执行查询:
while (sqlite3_step(statement) == SQLITE_ROW) {
int rowNum = sqlite3_column_int(statement, 0);
char *rowData = (char *)sqlite3_column_text(statement, 1);
NSString *fieldValue = [[NSString alloc] initWithUTF8String:rowData];
// Do something with the data here
}
sqlite3_finalize(statement);
使用过其他数据库的话应该很好理解这段语句,这个就是依次将每行的数据存在statement中,然后根据每行的字段取出数据。
(5)使用约束变量
实际操作时经常使用叫做约束变量的东西来构造SQL字符串,从而进行插入、查询或者删除等。
例如,要执行带两个约束变量的插入操作,第一个变量是int类型,第二个是C字符串:
char *sql = "insert into oneTable values (?, ?);";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(database, sql, -1, &stmt, nil) == SQLITE_OK) {
sqlite3_bind_int(stmt, 1, 235);
sqlite3_bind_text(stmt, 2, "valueString", -1, NULL);
}
if (sqlite3_step(stmt) != SQLITE_DONE)
NSLog(@"Something is Wrong!");
sqlite3_finalize(stmt);
这里,sqlite3_bind_int(stmt, 1, 235);有三个参数:
第一个是sqlite3_stmt类型的变量,在之前的sqlite3_prepare_v2中使用的。
第二个是所约束变量的标签index。
第三个参数是要加的值。
有一些函数多出两个变量,例如
sqlite3_bind_text(stmt, 2, "valueString", -1, NULL);
这句,第四个参数代表第三个参数中需要传递的长度。对于C字符串来说,-1表示传递全部字符串。
第五个参数是一个回调函数,比如执行后做内存清除工作。
接下来,做个小例子吧!
1、运行Xcode 4.3,新建一个Single View Application,名称为SQLite3 Test:

2、连接SQLite3库:
按照下图中的红色数字的顺序找到加号:

单击这个加号,打开窗口,在搜索栏输入sqlite3:

选择libsqlite3.dylib,单击Add,添加到工程。
3、进行界面设计。打开ViewController.xib,使用Interface Builder设计界面如下:

设置四个文本框的tag分别是1、2、3、4。
4、在ViewController.h中添加属性和方法:
@property (copy, nonatomic) NSString *databaseFilePath; - (void)applicationWillResignActive:(NSNotification *)notification;
5、打开ViewController.m,向其中添加代码:
5.1 在开头添加代码:
#import "sqlite3.h"
#define kDatabaseName @"database.sqlite3"
5.2 在@implementation之后添加代码:
@synthesize databaseFilePath;
5.3 在viewDidLoad方法中添加代码:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//获取数据库文件路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
self.databaseFilePath = [documentsDirectory stringByAppendingPathComponent:kDatabaseName];
//打开或创建数据库
sqlite3 *database;
if (sqlite3_open([self.databaseFilePath UTF8String] , &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, @"打开数据库失败!");
}
//创建数据库表
NSString *createSQL = @"CREATE TABLE IF NOT EXISTS FIELDS (TAG INTEGER PRIMARY KEY, FIELD_DATA TEXT);";
char *errorMsg;
if (sqlite3_exec(database, [createSQL UTF8String], NULL, NULL, &errorMsg) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, @"创建数据库表错误: %s", errorMsg);
}
//执行查询
NSString *query = @"SELECT TAG, FIELD_DATA FROM FIELDS ORDER BY TAG";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) {
//依次读取数据库表格FIELDS中每行的内容,并显示在对应的TextField
while (sqlite3_step(statement) == SQLITE_ROW) {
//获得数据
int tag = sqlite3_column_int(statement, 0);
char *rowData = (char *)sqlite3_column_text(statement, 1);
//根据tag获得TextField
UITextField *textField = (UITextField *)[self.view viewWithTag:tag];
//设置文本
textField.text = [[NSString alloc] initWithUTF8String:rowData];
}
sqlite3_finalize(statement);
}
//关闭数据库
sqlite3_close(database);
//当程序进入后台时执行写入数据库操作
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification
object:app];
}
5.4 在@end之前实现方法:
//程序进入后台时的操作,实现将当前显示的数据写入数据库
- (void)applicationWillResignActive:(NSNotification *)notification {
//打开数据库
sqlite3 *database;
if (sqlite3_open([self.databaseFilePath UTF8String], &database)
!= SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, @"打开数据库失败!");
}
//向表格插入四行数据
for (int i = 1; i <= 4; i++) {
//根据tag获得TextField
UITextField *textField = (UITextField *)[self.view viewWithTag:i];
//使用约束变量插入数据
char *update = "INSERT OR REPLACE INTO FIELDS (TAG, FIELD_DATA) VALUES (?, ?);";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) == SQLITE_OK) {
sqlite3_bind_int(stmt, 1, i);
sqlite3_bind_text(stmt, 2, [textField.text UTF8String], -1, NULL);
}
char *errorMsg = NULL;
if (sqlite3_step(stmt) != SQLITE_DONE)
NSAssert(0, @"更新数据库表FIELDS出错: %s", errorMsg);
sqlite3_finalize(stmt);
}
//关闭数据库
sqlite3_close(database);
}
6、实现关闭键盘,参考《iOS开发4:关闭键盘》中的第2步。其中,backgroundTap方法如下:
//关闭键盘
- (IBAction)backgroundTap:(id)sender {
for (int i = 1; i <= 4; i++) {
UITextField *textField = (UITextField *)[self.view viewWithTag:i];
[textField resignFirstResponder];
}
}
7、运行程序:
刚运行时显示如下面左图:

在各个文本框输入内容,如上面右图。然后按Home键,这样,就执行了写入数据的操作。
第一次运行程序时,在SandBox的Documents目录下出现数据库文件database.sqlite3:

此时退出程序,再次运行,则显示的就是上次退出时的值。
【转】iOS开发24:使用SQLite3存储和读取数据的更多相关文章
- iOS开发中视图控制器ViewControllers之间的数据传递
iOS开发中视图控制器ViewControllers之间的数据传递 这里我们用一个demo来说明ios是如何在视图控制器之间传递重要的参数的.本文先从手写UI来讨论,在下一篇文章中讨论在storybo ...
- iOS开发系列-常见离线存储方式
概述 在很多社交App手机在手机没有网络时,重新启动应用,依然能否展示上次访问的数据,提高用户体验,这个就是离线数据存储的运用场景.在iOS开发中常见的离线存储技术有Plist存储.个人偏好存储.解归 ...
- IOS开发-封装数据库sqlite3之为何选择FMDB
为什么使用第三方轻量级框架FMDB? FMDB是用于进行数据存储的第三方的框架,它与SQLite与Core Data相比较,存在很多优势. FMDB是面向对象的,它以OC的方式封装了SQLite的C语 ...
- IOS开发-本地持久化存储sqlite应用
前言 需求描述 开发测试环境 FMDB介绍 创建工程 一.前言 上一章介绍了如何开发一个IOS应用的入门案例教程: 我的第一个IOS开发应用 本章主要将介 ...
- [MISS静IOS开发原创文摘]-AppDelegate存储全局变量和 NSUserDefaults standardUserDefaults 通过模型保存和读取数据,存储自定义的对象
由于app开发的需求,需要从api接口获得json格式数据并保存临时的 app的主题颜色 和 相关url 方案有很多种: 1, 通过AppDelegate保存为全局变量,再获取 2,使用NSUSerD ...
- iOS开发——网络Swift篇&JSON与XML数据解析
JSON与XML数据解析 JSON数据解析(内置NSJSONSerialization与第三方JSONKit) 一,使用自带的NSJSONSerialization 苹果从IOS5.0后推出了SD ...
- iOS NSMutableDictionary中UIImage的存储和读取
思路:将UIImage转换成NSData,然后插入到NSMutableDictionary中.读取时,用NSData读出来,然后再转换成UIImage -存储 UIImage *image = [se ...
- iOS开发NSFetchedResultsController的使用CoreData和TableView数据同步更新
1.效果 2.代码 #import "ViewController.h" #import "Student+CoreDataProperties.h" #def ...
- iOS开发——网络Swift篇&NSURLSession加载数据、下载、上传文件
NSURLSession加载数据.下载.上传文件 NSURLSession类支持三种类型的任务:加载数据.下载和上传.下面通过样例分别进行介绍. 1,使用Data Task加载数据 使用全局的 ...
随机推荐
- Sass的控制命令(循环)
@if@if指令是一个SassScript,它可以根据条件来处理样式块,如果条件为true返回一个样式块,反之false返回另一个样式块.在Sass中除了@if,还可以配合@else if和@else ...
- (转)c#缓存介绍
在 ASP.NET 提供的许多特性中,缓存支持无疑是最值得欣赏的特性.相比 ASP.NET 的所有其他特性,缓存对应用程序的性能具有最大的潜在影响,利用缓存和其他机制,ASP.NET 开发人员可以接受 ...
- Google map实现类似Google earth的图标展开功能
前言 在Google map的开发时,如果有多个图标重叠在一起,这时下面的图标就点击不到.而在Google Earth中,鼠标一移到上面就会自动弹开,这对于用户而言是十分人性化的一个功能.如下是在Go ...
- static在类中的定义,和enum的用法
class A { // static int a = 1;//错误,静态变量在类外定义 static int a; static const int b = 1;//如果是静态成员常量,则可以在类内 ...
- 更换ios 开发者账号与下载别人的代码 真机调试时注意切换
Buid Setting search sign
- C#必须掌握的系统类
系统类 Type类,Object类,String类, Arrary类,Console类, Exception类,GC类, MarshalByRefObject类, Math类. DateTime结构 ...
- angular json转义html
第一步json输出的内容反编码 function htmldecode(s){ var div = document.createElement('div'); div.innerHTML = s; ...
- Mysql中natural join和inner join的区别
假设有如下两个表TableA,TableB TableA TableB Column1 Column2 Column1 Column3 1 2 1 3 TableA的Column1列名和TableB的 ...
- Mediawiki.org的PHP编码约定
http://www.mediawiki.org/wiki/Manual:Coding_conventions/PHP assignment作为expression来用看起来像个错误(looks su ...
- 解决IE10以下对象不支持“bind”属性或方法
IE10一下的浏览器,如果在JS代码中用了bind函数,那么就会报“SCRIPT438: 对象不支持“bind”属性或方法” 因为浏览器没有提供这个参数的方法,所以我们就自己写一个bind,来让这个参 ...