本地化存储

2016-07-09  本文已影响0人  火焰与柠檬

SQL基本操作

1.create 和 drop
2.增、改、删
insert
update
delete

数据类型

SQLite将数据划分为以下几种存储类型:

条件语句

where

例子:

(1)将t_student表中年龄大于10 并且 姓名不等于jack的记录,年龄都改为 5

update t_student set age = 5 where age > 10 and name != ‘jack’ ;

(2)删除t_student表中年龄小于等于10 或者 年龄大于30的记录

delete from t_student where age <= 10 or age > 30 ;

(3)将t_student表中名字等于jack的记录,score字段的值 都改为 age字段的

update t_student set score = age where name = ‘jack’ ;
select
limit(精准查询)

约束

简单约束
主键约束
外键约束
表连接查询

FMDB

主要的类
创建数据库
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
打开数据库

与数据库交互前,必须先打开数据库,如果资源或权限不足,将会打开失败。

if (![db open]) {    
        [db release];   
        return;    
    }  
执行更新

一切不是select的命令都是更新命令。执行更新会返回一个BOOL值。YES表示执行成功,否则有错误。相关方法:

使用executeUpdate:执行更新

-(BOOL)executeUpdate:(NSString*)sql, ...

-(BOOL)executeUpdateWithFormat:(NSString*)format, ...

-(BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments

示例:

[db executeUpdate:@"UPDATE t_student SET age = ? WHERE name = ?;", @20, @"Jack"]

[db executeUpdateWithFormat:@"INSERT INTO t_shop(name, price) VALUES (%@, %f);", shop.name, shop.price];

注意:参数必须是对象类型。比如要把int型变成NSNumber对象;

SQL中使用%要用%%;

执行查询

select命令,执行方法是以-excuteQuery开头的。

使用executeQuery:执行更新

-(FMResultSet *)executeQuery:(NSString*)sql, ...

-(FMResultSet *)executeQueryWithFormat:(NSString*)format, ...

-(FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments

示例:

// 查询数据
FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_student"];

// 遍历结果集
while ([rs next]) {
    NSString *name = [rs stringForColumn:@"name"];
    int age = [rs intForColumn:@"age"];
    double score = [rs doubleForColumn:@"score"];
}
类型转换

参数是查询结果集的列的索引位置

你无需调用 [FMResultSet close]来关闭结果集, 当新的结果集产生,或者其数据库关闭时,会自动关闭。

关闭数据库

使用完数据库后,关闭数据库连接来释放SQLite资源。

[db close]
事务和多线程

事务:是执行多个SQL语句时,如果有一个失败了,则回滚到原始状态。主要用来确保所有的SQL逻辑必须完成。

多线程:如果多个线程同时访问FMDatabase实例,会造成混乱,所以要用FMDatabaseQueue:

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
[queue inDatabase:^(FMDatabase *db) {
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
    
    FMResultSet *rs = [db executeQuery:@"select * from t_student"];
    while ([rs next]) {
        // …
    }
}];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
    
    FMResultSet *rs = [db executeQuery:@"select * from t_student"];
    while ([rs next]) {
        // …
    }
}];

事务回滚
*rollback = YES;

NSUserDefault

NSUserDefault:是一个单例,在整个程序中,只有一个实例对象,可以用于数据的永久保存,且简单实用,这是他可以让数据自由传递的一个前提(可以存储用户信息,夜间模式,字体大小)

其实存储后也是一个plist文件。

存储基本数据类型

示例:

//使用NSUserDefault进行存储
//1:创建要存储的数组
NSArray *array = @[@"11", @"22",@"33"];
//创建NSUserDefault对象
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
[user setObject:array forKey:@"userArray"];
NSLog(@"%@",user);

//读取
NSArray *newarr = [user objectForKey:@"userArray"];
NSLog(@"%@",newarr);

存储的对象必须是不可变,如果要存储可变的数组和字典,应该先转换成不可变的之后再存储。

存储自定义对象
//归档
-(void)encodeWithCoder:(NSCoder *)aCoder{
    unsigned int count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    for (int i = 0; i < count; i++) {
        const char * propertyCsString = property_getName(properties[i]);
        NSString   * propertyName  =  [NSString stringWithCString:propertyCsString encoding:NSUTF8StringEncoding];
        id           propertyValue =  [self valueForKey:propertyName];
        [aCoder encodeObject:propertyValue forKey:propertyName];
    }
    free(properties);
}
//解档
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    if (self) {
        unsigned int count;
        objc_property_t *properties = class_copyPropertyList([self class], &count);
        for (int i = 0; i < count; i++) {
            const char *property_csNam = property_getName(properties[i]);
            NSString   *p_key = [NSString stringWithCString:property_csNam encoding:NSUTF8StringEncoding];
            id value = [aDecoder decodeObjectForKey:p_key];   
            [self setValue:value forKey:p_key];
        }   
        free(properties);
    } 
return self
} 


 ///copy 协议
-(id)copyWithZone:(NSZone *)zone{
    StudentModel *s_model = [[self copyWithZone:zone] init];
    unsigned int count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    for (int i = 0; i < count; i++) {
        const char *propertyCS = property_getName(properties[i]);
        NSString *p_key = [NSString stringWithCString:propertyCS encoding:NSUTF8StringEncoding];
        id p_value = [self valueForKey:p_key];
        [s_model setValue:p_value forKey:p_key];
    }
    free(properties);
    return s_model;
}  
    StudentModel *s_model = [[StudentModel alloc] init];
    s_model.s_name = @"xiaoqiang";
    s_model.s_id = @"22";
    s_model.s_password = @"123456";
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:s_model];
    [u_default setObject:data forKey:@"s_student"];
    [u_default synchronize];
    NSData *rachiverData = [u_default objectForKey:@"s_student"];
    StudentModel *model = [NSKeyedUnarchiver unarchiveObjectWithData:rachiverData];
    NSLog(@"\n name is %@ \n id is %@ \n password is %@",model.s_name,model.s_id,model.s_password);

调用 synchronize 立刻同步数据到文件内,不然会有延迟。

[mySettingData synchronize];
删除对应的key
- (void)removeObjectForKey:(NSString *)defaultName;
//或者 
[[NSUserDefaults ] setObject:nil]

Plist

主要用来存储大文件。

缺点:需要将所有的数据取出再全部保存。

存储基本数据类型(array,dictionary,string,bool,date,data)
NSMutableDictionary *dict = [NSMutableDictionary dictionary];

[dict writeToFile:@"filePath" atomically:YES];

NSMutableArray *array = [NSMutableArray array];

[array writeToFile:@"filePath" atomically:YES];
//方法1:
NSString *filePath=[[NSBundle mainBundle] pathForResource:@"myDict" ofType:@"plist"];  
NSDictionary *myDic = [[NSDictionary alloc]initWithContentsOfFile:filePath];

NSString *filePath=[[NSBundle mainBundle] pathForResource:@"myArr" ofType:@"plist"];
NSArray *myArr2 = [[NSArray alloc] initWithContentsOfFile:filePath];

//方法2:
 NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
 NSString *filePath = [docPath stringByAppendingPathComponent: @"myData.plist"];
       
 NSDictionary *infoDic = [NSDictionary dictionaryWithContentsOfFile: filePath];
存储自定义数据类型
NSString *path = [self getPlistLibraryWithSuffix:@"test.plist"];

    NSMutableArray *stu_array = [NSMutableArray new];

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

        StudentModel *s_model = [StudentModel new];

        s_model.s_name = [NSString stringWithFormat:@"name%d",i];
        s_model.s_id = [NSString stringWithFormat:@"%d",100 + i];
        s_model.s_password = @"123456";
        [stu_array addObject:s_model];
    }
///写入
    NSData *archiverData = [NSKeyedArchiver archivedDataWithRootObject:stu_array];
    BOOL isSuc = [archiverData writeToFile:path atomically:YES];
//  BOOL isSuc = [NSKeyedArchiver archiveRootObject:stu_array toFile:path];
    NSLog(@"%d",isSuc);

  ///读取
    NSData *unarchiverData = [NSData dataWithContentsOfFile:path];
    NSArray *unArchiverArr = [NSKeyedUnarchiver unarchiveObjectWithData:unarchiverData];
//  NSArray *unArchiverArr = [NSKeyedUnarchiver unarchiveObjectWithFile:path];    
    NSLog(@"%@==",unArchiverArr);
删除plist文件
NSFileManager *fileManager = [NSFileManager defaultManager];

if ([fileManager isExecutableFileAtPath:@"filePath"]) {

    NSError *error;

    [fileManager removeItemAtPath:@"filePath" error:&error];
}

沙盒

沙盒的结构

总结:

相关操作
//Document
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
//library
NSString *libraryPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0];
//cache
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
//temp
NSString *tempPath =  NSTemporaryDirectory();
//document path
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
//test path
NSString *testPath= [documentsPath stringByAppendingPathComponent:@"test"];
//file path 
NSString *filePath = [testPath stringByAppendingString:@"file.plist"];

NSFileManager *fileManager = [NSFileManager defaultManager];
// 创建目录
[fileManager createDirectoryAtPath:testPath withIntermediateDirectories:YES attributes:nil error:nil];
// 创建文件
[fileManager createFileAtPath:filePath contents:nil attributes:nil];
NSArray *fileNameArrray = [fileManager subpathsOfDirectoryAtPath:documentsPath error:nil];

//可能目录比较深,耗性能
NSArray *fileNameArrray =  [fileManager subpathsAtPath:documentsPath];
//之后都在document文件夹中操作
[fileManager changeCurrentDirectoryPath:documentsPath];
//删除目录
[fileManager removeItemAtPath:documentsPath error:nil];
//删除文件
[fileManager removeItemAtPath:filePath error:nil];
NSString *temp = @"nihao 世界";
int dataInt = 1234;
float dataFloat = 3.14f;
//创建数据缓冲
NSMutableData *writer = [[NSMutableData alloc] init];
//将字符串添加到缓冲中
[writer appendData:[temp dataUsingEncoding:NSUTF8StringEncoding]];   
//将其他数据添加到缓冲中
[writer appendBytes:&dataInt length:sizeof(dataInt)];
[writer appendBytes:&dataFloat length:sizeof(dataFloat)];  
//将缓冲的数据写入到文件中
[writer writeToFile:path atomically:YES]; 
int intData;
float floatData = 0.0;
NSString *stringData;
    
NSData *reader = [NSData dataWithContentsOfFile:path];
stringData = [[NSString alloc] initWithData:[reader subdataWithRange:NSMakeRange(0, [temp length])]
                               encoding:NSUTF8StringEncoding];
[reader getBytes:&intData range:NSMakeRange([temp length], sizeof(intData))];
[reader getBytes:&floatData range:NSMakeRange([temp length] + sizeof(intData), sizeof(floatData))];
NSLog(@"stringData:%@ intData:%d floatData:%f", stringData, intData, floatData);

引用文章

参考NSUserDefault、Plist的解档和归档
FMDB的使用
本地数据持久化简述

上一篇下一篇

猜你喜欢

热点阅读