iOS常用5种数据存储方式详解

1.plist文件存储

每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离。应用必须待在自己的沙盒里,其他应用不能访问该沙盒

应用沙盒的文件系统目录,如下图所示(假设应用的名称叫Layer)

模拟器应用沙盒的根路径在: (apple是用户名, 6.0是模拟器版本)

/Users/apple/Library/Application Support/iPhone Simulator/6.0/Applications

Document :保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录

temp :保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录

Library/Caches :保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据

Library/Preference: 保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录

示例代码:

1 /** 保存数据*/ 2 - (IBAction)saveBtn 3 { 4     NSLog(@"保存"); 5     //1.获取沙盒根路径 6     NSString *homePath = NSHomeDirectory(); 7     //2.document路径 8     NSString *path = [homePath stringByAppendingPathComponent:@"Documents"]; 9     //3.新建数据10     NSArray *array = [NSArray arrayWithObjects:@"nan",@(22), nil];11     NSDictionary *dict = @{@"sss":@"sddd",@"ssssaw":@(1222)};12     13     14     //4.存储数据15     NSString *fullPath1 = [path stringByAppendingPathComponent:@"data1.plist"];16     NSString *fullPath2 = [path stringByAppendingPathComponent:@"data2.plist"];17     18     [array writeToFile:fullPath1 atomically:YES]; //数组写入plist19     [dict writeToFile:fullPath2 atomically:YES];20     21     NSLog(@"dict - %@",dict);22 }23 24 /** 读取数据*/25 - (IBAction)readBtn26 {27     //1.获取home目录28     NSString *home = NSHomeDirectory();29     //2.拼接Document目录30     NSString *path = [home stringByAppendingPathComponent:@"Documents"];31     //3.文件路径32     NSString *filePath1 = [path stringByAppendingPathComponent:@"data1.plist"];33     NSString *filePath2 = [path stringByAppendingPathComponent:@"data2.plist"];34     //读取文件35     NSArray *array = [NSArray arrayWithContentsOfFile:filePath1];36     NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath2];37     NSLog(@"array - %@, dict - %@",array , dict);38 }


缺点 : 只能存储含有 writeToFile:方法的对象,如NSDictionary,NSArray .

2.[b]NSUserDefaults( 偏好设置 ): [/b]
-- 存放目录 Library/Preference。
用来保存应用程序设置和属性、用户保存的数据,用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、 NSDictionary。如果要存储其他类型,则需要转换为前面的类型,才能用NSUserDefaults存储。很多iOS应用都支持偏好设置,比如保存用户名、密码、字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能,每个应用都有个NSUserDefaults实例,通过它来存取偏好设置
比如,保存用户名、字体大小、是否自动登录等。

示例代码:

/** 保存数据*/- (IBAction)save{    // 1.利用NSUserDefaults,就能直接访问软件的偏好设置(Library/Preferences)是个单例对象    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    //2.存储数据    [defaults setObject:@"sd" forKey:@"user"];    [defaults setObject:@"123w" forKey:@"test"];    [defaults setInteger:20 forKey:@"age"];    [defaults setBool:YES forKey:@"auto_login"];    //3.立刻同步(相当于更新数据)    [defaults synchronize];    }/** 读取数据*/- (IBAction)read{    //1.建立NSUserDefaults对象    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    //2.读取数据    NSString *user = [defaults objectForKey:@"user"];    NSString *test = [defaults objectForKey:@"test"];    NSInteger age = [defaults integerForKey:@"age"];    BOOL autoLogin = [defaults boolForKey:@"auto_login"];NSLog(@"user - %@/n test - %@/n age - %d/n autoLogin - %d/n,",user,test,age,autoLogin);}


注意 :UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize方法强制写入[defaults
synchornize];

缺点 : 本质还是plist文件存储,相对于plist文件存储来讲存储数据更快捷.

3.NSKeyedArchiver(NSCoding)

如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,可以直接用NSKeyedArchiver进行归档和恢复,不是所有的对象都可以直接用这种方法进行归档,只有遵守了NSCoding协议的对象才可以
NSCoding协议有2个方法:

encodeWithCoder:每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用encodeObject:forKey:方法归档实例变量;
initWithCoder:每次从文件中恢复(解码)对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forKey方法解码实例变量。

缺点 : 归档的形式来保存数据,只能一次性归档保存以及一次性解压。所以只能针对小量数据,而且对数据操作比较笨拙,即如果想改动数据的某一小部分,还是需要解压整个数据或者归档整个数据

示例代码:
1 #import <Foundation/Foundation.h> 2  3 @interface Person : NSObject <NSCoding> 4  5 @property (nonatomic , copy) NSString *name; 6 @property (nonatomic , assign) int age; 7 @property (nonatomic , assign) double height; 8  9 @end10 11 12 #import "Person.h"13 14 @implementation Person15 16 //归档的时候调用17 /** 将某个对象写入文件的时候会调用,在这个方法中说明哪些对象的哪些属性需要存储*/18 - (void)encodeWithCoder:(NSCoder *)enCoder19 {20     NSLog(@"enCoder - %@",enCoder);21     [enCoder encodeObject:self.name forKey:@"name"];22     [enCoder encodeInt:self.age forKey:@"age"];23     [enCoder encodeDouble:self.height forKey:@"height"];24     25 }26 27 /** 解档时候调用,在这个方法中说清楚哪些属性要解档*/28 - (id)initWithCoder:(NSCoder *)decoder29 {30     if (self = [super init])31     {32 //读取文件内容33 self.name = [decoder decodeObjectForKey:@"name"];34 self.age = [decoder decodeIntForKey:@"age"];35 self.height = [decoder decodeDoubleForKey:@"height"];36 37     }38     39     return self;40 }41 42 43 @end44 45 46 #import "SDViewController.h"47 #import "Person.h"48 49 @interface SDViewController ()50 51 @end52 53 @implementation SDViewController54 55 - (void)viewDidLoad56 {57     [super viewDidLoad];58     59     60 }61 62 - (IBAction)save63 {64     //1.数据对象65     Person *p1 = [[Person alloc] init];66     p1.name = @"王麻子";67     p1.age = 20;68     p1.height = 1.98;69     Person *p2 = [[Person alloc] init];70     p2.name = @"李四";71     p2.age = 56;72     p2.height = 1.68;73     //2.归档数据对象74     //2.1获得文件的Documents全路径75     NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];76     //2.2获得文件的全路径77     NSString *path = [doc stringByAppendingPathComponent:@"person.txt"];78     //2.3将对象归档79     [NSKeyedArchiver archiveRootObject:p1 toFile:path];80     81 }82 - (IBAction)read83 {84     // 1.获得Documents的全路径85     NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];86     // 2.获得文件的全路径87     NSString *path = [doc stringByAppendingPathComponent:@"person.txt"];88     // 3.从文件中读取Person对象89     Person *p3 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];90     91     NSLog(@"%@ %d %f", p3.name, p3.age, p3.height);92 93 }94 95 96 @end


NSKeyedArchiver-归档对象的注意:

如果父类也遵守了NSCoding协议,请注意:

应该在encodeWithCoder:方法中加上一句[super encodeWithCode:encode];确保继承的实例变量也能被编码, 也能被归档;
应该在initWithCoder:方法中加上一句self = [super initWithCoder:decoder];确保继承的实例变量也能被解码,即也能被恢复; 
但有时候可能想将多个对象写入到同一个文件中,那么就要使用NSData来进行归档对象,NSData可以为一些数据提供临时存储空间,以便随后写入文件,或者存放从磁盘读取的文件内容。

示例代码:

1 Person.h里面



3 #import <Foundation/Foundation.h>



5 @interface Person : NSObject <NSCoding>



7 @property (nonatomic , copy) NSString *name;

8 @property (nonatomic , assign) int age;

9 @property (nonatomic , assign) double height;

10 

11 @end

12 

13 Person.m里面

14 #import "Person.h"

15 

16 @implementation Person

17 

18 //归档的时候调用

19 /** 将某个对象写入文件的时候会调用,在这个方法中说明哪些对象的哪些属性需要存储*/

20 - (void)encodeWithCoder:(NSCoder *)enCoder

21 {

22 NSLog(@"enCoder - %@",enCoder);

23 [enCoder encodeObject:self.name forKey:@"name"];

24 [enCoder encodeInt:self.age forKey:@"age"];

25 [enCoder encodeDouble:self.height forKey:@"height"];

26 

27 }

28 

29 /** 解档时候调用,在这个方法中说清楚哪些属性要解档*/

30 - (id)initWithCoder:(NSCoder *)decoder

31 {

32 if (self = [super init])

33 {
34 //读取文件内容
35
self.name= [decoder decodeObjectForKey:@"name"];
36 self.age = [decoder decodeIntForKey:@"age"];

37 self.height = [decoder decodeDoubleForKey:@"height"];

38 

39 }

40 

41 return self;

42 }

43 

44 

45 @end

46 

47 SDViewController.m里面

48 

49 #import "SDViewController.h"

50 #import "Person.h"

51 

52 @interface SDViewController ()

53 

54 @end

55 

56 @implementation SDViewController

57 

58 - (void)viewDidLoad

59 {

60 [super viewDidLoad];

61 // Do any additional setup after loading the view, typically from a nib.

62 

63 }

64 

65 - (void)didReceiveMemoryWarning

66 {

67 [super didReceiveMemoryWarning];

68 // Dispose of any resources that can be recreated.

69 }

70 

71 

72 - (IBAction)save

73 {

74 //1.数据对象

75 Person *p1 = [[Person alloc] init];

76 p1.name = @"王麻子";

77 p1.age = 20;

78 p1.height = 1.98;

79 Person *p2 = [[Person alloc] init];

80 p2.name = @"李四";

81 p2.age = 56;

82 p2.height = 1.68;

83 //2.归档数据对象

84 //2.1获得文件的Documents全路径

85 NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];

86 //2.2获得文件的全路径

87 NSString *path = [doc stringByAppendingPathComponent:@"person.txt"];

88 // 
//2.3将对象归档

89 // [NSKeyedArchiver archiveRootObject:p1 toFile:path];

90 // 

91 // 新建一块可变数据区

92 NSMutableData *data = [NSMutableData data];

93 // 将数据区连接到一个NSKeyedArchiver对象

94 NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

95 [archiver encodeObject:p1 forKey:@"person1"];

96 [archiver encodeObject:p2 forKey:@"person2"];

97 // 存档完毕(一定要调用这个方法)

98 [archiver finishEncoding];

99 //将存档的数据写入文件

100 [data writeToFile:path atomically:YES];

101 

102 }

103 - (IBAction)read

104 {

105 // 1.获得Documents的全路径

106 NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

107 // 2.获得文件的全路径

108 NSString *path = [doc stringByAppendingPathComponent:@"person.txt"];

109 // 3.从文件中读取Student对象

110 // Person *p3 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

111 NSData *data = [NSData dataWithContentsOfFile:path];

112 

113 // 根据数据,解析成一个NSKeyedUnarchiver对象

114 NSKeyedUnarchiver *unchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];

115 Person *p1 = [unchiver decodeObjectForKey:@"person1"];

116 Person *p2 = [unchiver decodeObjectForKey:@"person2"];

117 [unchiver finishDecoding];

118 NSLog(@"%@ %d %f", p1.name, p1.age, p1.height);

119 NSLog(@"%@ %d %f", p2.name, p2.age, p2.height);

120 

121 }

122 

123 

124 
125 @end

附:
NSCoder.h

- (void)encodeValueOfObjCType:(const char *)type at:(const void *)addr; //解档C类型数据,addr传入地址

- (void)encodeDataObject:(NSData *)data; //归档一个NSData型对象

- (void)decodeValueOfObjCType:(const char *)type at:(void *)data; 解档C类型数据

- (NSData *)decodeDataObject;//解档一个NSData型对象

@end


@interface NSCoder (NSExtendedCoder)

/** 归档相关函数*/

- (void)encodeObject:(id)object;

- (void)encodeRootObject:(id)rootObject;

- (void)encodeBycopyObject:(id)anObject;

- (void)encodeByrefObject:(id)anObject;

- (void)encodeConditionalObject:(id)object;

- (void)encodeValuesOfObjCTypes:(const char *)types, ...;

- (void)encodeArrayOfObjCType:(const char *)type count:(NSUInteger)count at:(const void *)array;

- (void)encodeBytes:(const void *)byteaddr length:(NSUInteger)length;



/** 解档相关函数*/

- (id)decodeObject;

- (void)decodeValuesOfObjCTypes:(const char *)types, ...;

- (void)decodeArrayOfObjCType:(const char *)itemType count:(NSUInteger)count at:(void *)array;

- (void *)decodeBytesWithReturnedLength:(NSUInteger *)lengthp NS_RETURNS_INNER_POINTER;

- (unsigned)systemVersion;



//是否遵循KeyedCoding

- (BOOL)allowsKeyedCoding;


/** 归档相关函数*/

- (void)encodeObject:(id)objv forKey:(NSString *)key;

- (void)encodeConditionalObject:(id)objv forKey:(NSString *)key;

- (void)encodeBool:(BOOL)boolv forKey:(NSString *)key;

- (void)encodeInt:(int)intv forKey:(NSString *)key;

- (void)encodeInt32:(int32_t)intv forKey:(NSString *)key;

- (void)encodeInt64:(int64_t)intv forKey:(NSString *)key;

- (void)encodeFloat:(float)realv forKey:(NSString *)key;

- (void)encodeDouble:(double)realv forKey:(NSString *)key;

- (void)encodeBytes:(const uint8_t *)bytesp length:(NSUInteger)lenv forKey:(NSString *)key;



/** 解档相关函数*/

- (BOOL)containsValueForKey:(NSString *)key;

- (id)decodeObjectForKey:(NSString *)key;

- (BOOL)decodeBoolForKey:(NSString *)key;

- (int)decodeIntForKey:(NSString *)key;

- (int32_t)decodeInt32ForKey:(NSString *)key;

- (int64_t)decodeInt64ForKey:(NSString *)key;

- (float)decodeFloatForKey:(NSString *)key;

- (double)decodeDoubleForKey:(NSString *)key;

- (const uint8_t *)decodeBytesForKey:(NSString *)key returnedLength:(NSUInteger *)lengthp NS_RETURNS_INNER_POINTER; // returned bytes immutable!



- (void)encodeInteger:(NSInteger)intv forKey:(NSString *)key NS_AVAILABLE(10_5, 2_0);

- (NSInteger)decodeIntegerForKey:(NSString *)key NS_AVAILABLE(10_5, 2_0);



// Returns YES if this coder requires secure coding. Secure coders check a list of allowed classes before decoding objects, and all objects must implement NSSecureCoding.

//是否安全解档

- (BOOL)requiresSecureCoding NS_AVAILABLE(10_8, 6_0);

4. Write写入方式 :永久保存在磁盘中。
具体方法为:

[b]第一步:获得文件即将保存的路径: [/b]
方法1:

NSArray*documentPaths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

//使用C函数NSSearchPathForDirectoriesInDomains来获得沙盒中目录的全路径。该函数有三个参数,目录类型、he domain mask、布尔值。其中布尔值表示是否需要通过“~”扩展路径。而且第一个参数是不变的,即为NSSearchPathDirectory。在IOS中后两个参数也是不变的,即为:NSUserDomainMask和YES。

NSString *ourDocumentPath =[documentPaths objectAtIndex:0];

方法2:
使用NSHomeDirectory函数获得sandbox的路径。
具体的用法为:

NSString *sandboxPath = NSHomeDirectory();// Once you have the fullsandbox path, you can create a path from it,但是不能在sandbox的本文件层上写文件也不能创建目录,而应该是此基础上创建一个新的可写的目录,例如Documents,Library或者temp。
NSString *documentPath = [sandboxPath stringByAppendingPathComponent:@"Documents"];//将Documents添加到sandbox路径上,具体原因前面分析了!

区别: 使用NSSearchPathForDirectoriesInDomains比在NSHomeDirectory后面添加Document更加安全。因为该文件目录可能在未来发送的系统上发生改变。

第二步:生成在该路径下的文件:

NSString *FileName=[documentDirectory stringByAppendingPathComponent:fileName];//fileName就是保存文件的文件名

第三步:往文件中写入数据:

[datawriteToFile:FileName atomically:YES];//将NSData类型对象data写入文件,文件名为FileName

最后:从文件中读出数据:

NSDatadata=[NSDatadataWithContentsOfFile:FileName options:0 error:NULL];//从FileName中读取出数据

5.SQLite3 

SQLite3是一款开源的嵌入式关系型数据库,可移植性好、易使用、内存开销小.SQLite3是无类型的,意味着你可以保存任何类型的数据到任意表的任意字段中。

数据库语句

/*简单约束*/

//如果表不存在就创建一张t_student的表(id为主键,自动增长,name text类型,age integer类型);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER);

//如果表不存在就创建一张t_student的表(id为主键,自动增长,name text类型不能为空,age integer类型不能为空);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER NOT NULL);

//如果表不存在就创建一张t_student的表(id为主键,自动增长,name text类型,并且每一个是唯一的,age integer类型不能为空);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER);

//如果表不存在就创建一张t_student的表(id为主键,自动增长,name text类型,age integer类型默认为1);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER DEFAULT 1);



/*分页*/

//先将表按照升序排,跳过最前面30条语句,然后取10条记录

SELECT * FROM t_student ORDER BY id ASC LIMIT 30, 10;



/*排序*/

//取出表中score > 50的数据并按照降序排列

SELECT * FROM t_student WHERE score > 50 ORDER BY age DESC;

//取出表中score<50的数据并按照升序排列,score>50的数据按照降序排列

SELECT * FROM t_student WHERE score < 50 ORDER BY age ASC , score DESC;



/*计量*/

//统计表中age > 50的个数

SELECT COUNT(*) FROM t_student WHERE age > 50;



/*别名*/

//将name 命名为 myName, age 命名为 myAge, score 命名为myScore

SELECT name as myName, age as myAge, score as myScore FROM t_student;

//将name 命名为 myName, age 命名为 myAge, score 命名为myScore

SELECT name myName, age myAge, score myScore FROM t_student;

//给t_student表起个别名叫做s,利用s来引用表中的字段,取出age > 50 的数据,将name 命名为 myName, age 命名为 myAge, score 命名为myScore

SELECT s.name myName, s.age myAge, s.score myScore FROM t_student s WHERE s.age > 50;



/*查询*/

//从表中查询name,age,score

SELECT name, age, score FROM t_student;

//查询整张表

SELECT * FROM t_student;



/*修改指定数据*/

//从表中取出age = 10 的那条数据,将name 字段值设为MM

UPDATE t_student SET name = 'MM' WHERE age = 10;

/从表中取出age = 7 的那条数据,将name 字段值设为WW

UPDATE t_student SET name = 'WW' WHERE age is 7;

//取出表中age < 20 的数据,并将name 全部设置为XXOO

UPDATE t_student SET name = 'XXOO' WHERE age < 20;

//取出表中age < 50 并且 score > 10的数据,将满足条件的每一条数据中的name字段设置为NNMM

UPDATE t_student SET name = 'NNMM' WHERE age < 50 and score > 10;



/*删除数据*/

//删除表中的数据

DELETE FROM t_student;



/*更新数据*/

//将表中的name字段全部设置为MM

UPDATE t_student SET name = 'MM';



/*插入数据*/

//往表中插入一条数据(name = jonathan , age = 28, score = 100)

INSERT INTO t_student(age, score, name) VALUES ('28', 100, 'jonathan');

//往表中插入一条数据(name = lee , age = 28)

INSERT INTO t_student(name, age) VALUES ('lee', '28');

//往表中插入一条数据(score = 100)

INSERT INTO t_student(score) VALUES (100);



/*添加主键*/

//如果表不存在就创建一张表,id为主键自动增长,integer类型,name 为text类型,age 为integer类型,score为浮点类型

CREATE TABLE IF NOT EXISTS t_student (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, score REAL);



/*删除表*/

//销毁t_student表

DROP TABLE t_student;

//如果表存在就销毁这张表

DROP TABLE IF EXISTS t_student;



/****************************************************** 应 用 *****************************************************************/

- (void)viewDidLoad

{

[super viewDidLoad];

// 1.打开创建一个数据库

NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

NSString *fileName = [path stringByAppendingPathComponent:@"t_student.sqlite"];

int result = sqlite3_open(fileName.UTF8String, &_db);



if (result == SQLITE_OK) {

// 创建表

const char *sql = "CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , name TEXT NOT NULL, age INTERGER NOT NULL);";

char *error = nil;

sqlite3_exec(self.db, sql, NULL, NULL, &error);

if (error) {

NSLog(@"创建失败");

}else{

NSLog(@"创建成功");

}

}else{

NSLog(@"失败");

}



}

/**

* 增加

*/

- (IBAction)insertBtnClick:(id)sender {

for (int i = 0; i < 100; i++) {

NSString *name = [NSString stringWithFormat:@"lee-%d", i];

int age = arc4random_uniform(50) + 50;

NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_student(name, age) VALUES ('%@', %d);", name, age];

char *error = nil;

sqlite3_exec(self.db, sql.UTF8String, NULL, NULL, &error);



if (error) {

NSLog(@"创建失败");

}else{

NSLog(@"创建成功");

}

}

}

/**

* 更新

*/

- (IBAction)updateBtnClick:(id)sender {

const char *sql = "UPDATE t_student SET name = 'DG';";

char *error = nil;

sqlite3_exec(self.db, sql, NULL, NULL, &error);



if (error) {

NSLog(@"更新失败");

}else{

NSLog(@"更新成功");

}

}

/**

* 删除

*/

- (IBAction)deleteBtnClick:(id)sender {

const char *sql = "DELETE FROM t_student;";

char *error = nil;

sqlite3_exec(self.db, sql, NULL, NULL, &error);

if (error) {

NSLog(@"删除失败");

}else{

NSLog(@"删除成功");

}

}

/**

* 查询

*/

- (IBAction)selectBtnClick:(id)sender {

const char *zSql = "SELECT * FROM t_student";

sqlite3_stmt *stmt;

// 查询前的准备, 检查sql语句是否正确

int result = sqlite3_prepare_v2(self.db, zSql, -1, &stmt, NULL);

if(result == SQLITE_OK) { // 准备完成,没有错误

// 提取查询到得数据到stmt, 一次提取一条

while(sqlite3_step(stmt) == SQLITE_ROW){

// 取出提取到得记录(数据)中的第0列数据和第一列数据

const unsigned char *name = sqlite3_column_text(stmt, 0);

int age = sqlite3_column_int(stmt, 1);

NSLog(@"%s, %d", name, age);

}

}

}

SqLite3小结

1.打开数据库

int sqlite3_open(

const char *filename, // 数据库的文件路径

sqlite3 **.ppDb // 数据库实例

);



2.执行任何SQL语句

int sqlite3_exec(

sqlite3*, // 一个打开的数据库实例

const char *sql, // 需要执行的SQL语句

int (*callback)(void*,int,char**,char**), // SQL语句执行完毕后的回调

void *, // 回调函数的第1个参数

char **errmsg // 错误信息

);



3.检查SQL语句的合法性(查询前的准备)

int sqlite3_prepare_v2(

sqlite3 *db, // 数据库实例

const char *zSql, // 需要检查的SQL语句

int nByte, // SQL语句的最大字节长度

sqlite3_stmt **ppStmt, // sqlite3_stmt实例,用来获得数据库数据

const char **pzTail

);



4.查询一行数据

int sqlite3_step(sqlite3_stmt*); // 如果查询到一行数据,就会返回SQLITE_ROW



5.利用stmt获得某一字段的值(字段的下标从0开始)

double sqlite3_column_double(sqlite3_stmt*, int iCol); // 浮点数据

int sqlite3_column_int(sqlite3_stmt*, int iCol); // 整型数据

sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); // 长整型数据

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); // 二进制文本数据

const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); // 字符串数据



6.SqLite3第三方框架FMDB使用小结

FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API.

FMDB的优点

@1使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码

@2对比苹果自带的Core Data框架,更加轻量级和灵活

@3提供了多线程安全的数据库操作方法,有效地防止数据混乱
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值