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

来源:互联网 发布:java读取文件乱码 编辑:程序博客网 时间:2024/06/06 05:34
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.NSUserDefaults(偏好设置):-- 存放目录 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里面
  2 
  3 #import <Foundation/Foundation.h>
  4 
  5 @interface Person : NSObject <NSCoding>
  6 
  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写入方式:永久保存在磁盘中。
具体方法为:
 
第一步:获得文件即将保存的路径:
方法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提供了多线程安全的数据库操作方法,有效地防止数据混乱
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 dnf邮件发错了怎么办 手机提示sd卡已损坏怎么办 解压包文件数据损坏该怎么办 电脑被压缩后电脑打不开怎么办 眼睛里进了飞虫怎么办 虫子飞到眼睛里怎么办 云电脑pc版双鼠标怎么办 电脑蓝屏代码7f怎么办 笔记本电脑蓝屏开不了机怎么办 装xp系统后蓝屏怎么办 一键ghost断电了怎么办 如何防止cpu降频怎么办 win7 64位系统不兼容怎么办 网页无法加载打印机插件怎么办 微信提示安装了插件怎么办 电脑上不了网怎么办 win10 win10电脑突然没网了怎么办 笔记本玩战争前线发热严重怎么办 玩战争前线总是闪退怎么办 uu加速器卡在29怎么办 新ipad下载不了东西怎么办 福昕pdf阅读器找不到图章怎么办 战地4没达到分数怎么办 植物在太暗环境怎么办 玩绝地求生机型不支持怎么办 安卓安装包损坏怎么办 方舟手游安装包损坏怎么办 7p新机耗电快怎么办 不小心把图片删了怎么办 腿上毛又长又多怎么办 征兵体检体重太轻怎么办 体检发现颈部有淋巴节怎么办? 4岁宝宝汗毛重怎么办 嘴巴张开闭不上怎么办 口张开闭不上怎么办 要去当兵有痔疮怎么办 狗舔的东西吃了怎么办 婚检说生过孩子怎么办 劳动法规定身体有疾病的怎么办 铁路对职工醉驾怎么办 入职体检高血糖怎么办