ios学习笔记-数据持久化

沙盒

沙盒是一种数据安全策略,只允许自己的应用访问目录。可以使用NSHomeDirectory()获取。

ios沙盒下有三个子目录:

1.Documents目录:用于存储比较大的文件活着需要频发女更新的数据,需要持久化的数据。获取代码:

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

2.Library目录: 该目录下有Preferences和Caches两个目录。前者用于存放应用程序的设置数据和状态信息,后者用于存储缓存文件。获取代码:

NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];

3.tmp目录:临时文件目录,随应用程序退出而清除,不能进行iTunes或iCloud备份。获取代码:

NSString *tempPath = NSTemporaryDirectory();

属性列表(plist文件)

属性列表是一种XML文件。NSArray和NSDictionary类提供了读写plist文件的方法。

  • +arrayWithContentsOfFile:。NSArray类的类方法用于读取plist文件。
  • +dictionaryWithContentsOfFile:。NSDictionary类的类方法用于读取plist文件。
  • - initWithContentsOfFile:。NSArray和NSDictionary类都拥有此构造器方法,也能读取plist文件。
  • - writeToFile:atomically:。用于写入plist文件。atomically参数为是否适用辅助文件,如果为true则先写入到辅助文件中,然后将辅助文件重命名为目标文件。如果为false,则直接写入目标文件。

示例代码(写入):  

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

NSString *path = [documentPath stringByAppendingPathComponent:@"plist.plist"];

NSArray *array = @[@"a",@"b",@"c",@"d"];
    
NSString *plistPath = [self applicationDocumentsDirectoryFile];
    
[array writeToFile:plistPath atomically:YES];

示例代码(读取):

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    
NSString *path = [documentPath stringByAppendingPathComponent:@"plist.plist"];

NSArray *array = [NSArray arrayWithContentsOfFile:path];

NSLog(@"%@",array);

对象归档

归档是一种序列化方式。需要归档对象的类必须实现NSCoding协议,而且每个成员变量应该是基本数据类型或实现NSCoding协议的某个类的实例。

写入:

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    
NSString *path = [documentPath stringByAppendingPathComponent:@"plist.plist"];

NSDictionary *array = @{@"1":@"a",@"2":@"b"};
    
[NSKeyedArchiver archiveRootObject:array toFile:path];

读取:

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    
NSString *path = [documentPath stringByAppendingPathComponent:@"plist.plist"];

NSDictionary *array = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    
NSLog(@"%@",array);

SQLite数据库

SQLite可移植性强、小而容易使用。在运行时与实用他的程序共用相同的进程空间,不是单独的两个进程。在SQLite中,支持的常见数据类型有以下几种:

  • INTEGER。整型
  • REAL。浮点型
  • TEXT。字符串类型,采用UTF-8,UTF-16字符编码
  • BLOB。二进制,能存放任何二进制数据。

在SQLite中没有布尔类型,可采用整数0和1代替。也没有日期和时间类型,它们存储在TEXT、REAL、INTEGER类型中。

打开数据库:

/**
 *  获取沙盒路径
 *
 *  @return 沙盒路径
 */
- (NSString *)dataFilePath {
    
    NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    
    NSString *document = [path objectAtIndex:0];
    
    return [document stringByAppendingPathComponent:@"sqlite"];
    
}

/**
 *  打开数据库,如果没有则创建
 */
- (void)openSqlite {
    sqlite3 *database;
    //参数一:数据库文件路径(char类型) 参数二:数据库指针变量
    if (sqlite3_open([[self dataFilePath] UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO, @"open database faid!");
        NSLog(@"数据库创建失败");
    }
    else {
        char *err;
        //如果没有Note表则创建。PRIMARY KEY 主键
        NSString *sql = @"CREATE TABLE IF NOT EXISTS Note (cdate TEXT PRIMARY KEY,content TEXT)";
        //参数一:数据库指针变量 参数二:sql语句(char类型) 参数三:回调函数 参数四:回调函数所需参数
        if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK) {
            sqlite3_close(database);
            NSAssert(NO, @"建表失败");
        }
        
        //数据库打开失败,SQL语句执行失败,以及执行成功都需要关闭数据库,释放资源
        sqlite3_close(database);
    }
}

条件查询:

/**
 *  根据条件查询一条
 *
 *  @param text 主键
 *
 *  @return 查询结果
 */
- (NSDictionary *)findById:(NSString *)text {
    sqlite3 *database;
    NSString *path = [self dataFilePath];
    if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO, @"数据库打开失败");
    }
    else {
        NSString *sql = @"SELECT cdate,content FROM Note where cdate = ?";
        
        NSLog(@"打开数据库");
        
        //语句对象,SQL语句通过它执行
        sqlite3_stmt *statement;
        
        /*
         预处理过程
sqlite3_prepare_v2函数是SQL预处理语句。将SQL编译成二进制代码,提高执行速度 参数一:数据库指针变量 参数二:sql语句 参数三:全部SQL字符串长度。 如果nByte小于0,则函数取出zSql中从开始到第一个0终止符的内容;如果nByte不是负的,那么它就是这个函数能从zSql中读取的字节数的最大值。如果nBytes非负,zSql在第一次遇见’/000/或’u000’的时候终止 参数四:statement指针 参数五:SQL语句没有执行的部分语句。 上面提到zSql在遇见终止符或者是达到设定的nByte之后结束,假如zSql还有剩余的内容,那么这些剩余的内容被存放到pZTail中,不包括终止符
*/ int result = sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL); NSLog(@"___________ %d",result); if (result == SQLITE_OK) { NSLog(@"预处理"); /* sqlite3_bind_text:用于绑定SQL语句的参数 参数一:statement指针 参数二:参数序号(从1开始) 参数三:SQL语句参数(char类型) 参数四:字符串长度 参数五:函数指针,当数据库操作完成后会调用该函数 */ sqlite3_bind_text(statement, 1, [text UTF8String], -1, NULL); //执行。如果返回值为SQLITE_ROW说明数据没有遍历完 if (sqlite3_step(statement) == SQLITE_ROW) { /* 读取字符串类型的字段,第二个参数为select语句的索引(从0开始),下面就是读取cdata。 读取字段函数与字段类型对应,读取字段函数如下: sqlite3_column_blob() sqlite3_column_double() sqlite3_column_int() sqlite3_column_int64() sqlite3_column_text() sqlite3_column_text16() */ char *bufData = (char *)sqlite3_column_text(statement, 0); NSString *strData = [[NSString alloc] initWithUTF8String:bufData]; //读取content char *bufContent = (char *)sqlite3_column_text(statement, 1); NSString *strContent = [[NSString alloc] initWithUTF8String:bufContent]; NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:strData,@"data",strContent,@"content", nil]; return dict; } } //释放statement sqlite3_finalize(statement); sqlite3_close(database); } return nil; }

查询全部:

/**
 *  查询全部数据
 *
 *  @return 数组
 */
- (NSMutableArray *)findAll {
    sqlite3 *database;
    NSMutableArray *array = [[NSMutableArray alloc] init];
    NSString *path = [self dataFilePath];
    if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO, @"数据库打开失败");
    }
    else {
        NSString *sql = @"SELECT cdate,content FROM Note";
        
        sqlite3_stmt *statement;
        if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL) == SQLITE_OK) {
            
            while (sqlite3_step(statement) == SQLITE_ROW) {
                char *bufData = (char *)sqlite3_column_text(statement, 0);
                NSString *strData = [[NSString alloc] initWithUTF8String:bufData];
                
                NSLog(@"strData = %@",strData);
                
                char *bufContent = (char *)sqlite3_column_text(statement, 1);
                NSString *strContent = [[NSString alloc] initWithUTF8String:bufContent];
                
                NSLog(@"strContent = %@",strContent);
                
                NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:strData,@"data",strContent,@"content", nil];
                [array addObject:dict];
            }
            
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(database);
    }
    return array;
}

添加数据:

/**
 *  添加数据
 *
 *  @param model 所要插入的数据
 */
- (void)insert:(NSDictionary *)model {
    sqlite3 *database;
    NSString *path = [self dataFilePath];
    if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO, @"数据库打开失败");
    }
    else {
        NSString *sql = @"INSERT OR REPLACE INTO Note(cdate,content) VALUES(?,?)";
        
        sqlite3_stmt *statement;
        if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL) == SQLITE_OK) {
            
            char *bufData = (char *)[[model objectForKey:@"date"] UTF8String];
            NSString *strContent = [model objectForKey:@"content"];
            char *bufContent = (char *)[strContent UTF8String];
            
            sqlite3_bind_text(statement, 1, bufData, -1, NULL);
            sqlite3_bind_text(statement, 2, bufContent, -1, NULL);
            
            if (sqlite3_step(statement) != SQLITE_DONE) {
                NSAssert(NO, @"插入数据失败");
            }
            else {
                NSLog(@"插入成功");
            }
            
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(database);
    }
}

修改数据:

/**
 *  添加数据
 *
 *  @param model 所要插入的数据
 */
- (void)insert:(NSDictionary *)model {
    sqlite3 *database;
    NSString *path = [self dataFilePath];
    if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO, @"数据库打开失败");
    }
    else {
        NSString *sql = @"INSERT OR REPLACE INTO Note(cdate,content) VALUES(?,?)";
        
        sqlite3_stmt *statement;
        if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL) == SQLITE_OK) {
            
            char *bufData = (char *)[[model objectForKey:@"date"] UTF8String];
            NSString *strContent = [model objectForKey:@"content"];
            char *bufContent = (char *)[strContent UTF8String];
            
            sqlite3_bind_text(statement, 1, bufData, -1, NULL);
            sqlite3_bind_text(statement, 2, bufContent, -1, NULL);
            
            if (sqlite3_step(statement) != SQLITE_DONE) {
                NSAssert(NO, @"插入数据失败");
            }
            else {
                NSLog(@"插入成功");
            }
            
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(database);
    }
}

删除数据:

/**
 *  删除数据
 *
 *  @param cdata 所要删除数据的主键
 */
- (void)remove:(NSString *)cdata {
    sqlite3 *database;
    NSString *path = [self dataFilePath];
    
    if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO, @"数据库打开失败");
    }
    else {
        NSString *sql = @"DELETE from Note where cdate =?";
        
        sqlite3_stmt *statement;
        if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL) == SQLITE_OK) {
            
            sqlite3_bind_text(statement, 1, [cdata UTF8String], -1, NULL);
                
                int result = sqlite3_step(statement);
            
                if (result != SQLITE_DONE) {
                    NSAssert(NO, @"删除数据失败");
                }
                else {
                    NSLog(@"删除数据成功");
                }
            
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(database);
    }
}

 

posted @ 2015-10-25 20:36  黑夜里的猫  阅读(183)  评论(0编辑  收藏  举报