iOS之数据本地持久化

前言

  • 每个iOS应用软件都有一个单独的文件目录,这个目录我们称之为沙盒。可以通过NSHomeDirectory()来获取当前应用软件的根目录。

  • 沙盒目录(此处来源简书,参考作者ParadiseKiss)https://www.jianshu.com/p/a620b8ae7ab7

    • Documents:保存用户产生的数据,iTunes同步设备的时候会备份该目录。用户产生的数据就是指用户在使用当前app的时候保存的一些数据,比如保存app中的图片、保存下载的文件等。

    • Library:这个目录下有2个文件夹,一个是Caches、一个是Preferences,Caches主要保存缓存数据,比如SDWebImage把缓存的图片就存放到该目录下。当程序退出后,改目录保存的文件一直存在。

      Preferences在Xcode6之前保存的是偏好设置,比如NSUserDefaults保存的文件。但是Xcode6以上就保存到/Users/用户名/Library/ Developer/CoreSimulator/Devices/模拟器UDID/data/Library/Preferences/文件夹下。

  • tmp:保存程序中的临时数据,当程序退出后系统会自动删除tmp中所有的文件。

// 获取Documents路径
 NSString*docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) firstObject];

//获取Library的路径
 NSString*libDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask,YES) lastObject];

// 获取cache路径
 NSString*cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES) firstObject];

// 获取tmp路径
 NSString*tmpDir =NSTemporaryDirectory();


本地数据五种持久化方式

  • NSUserDefaults (偏好设置)
  • plist文件(属性列表)
  • NSKeyedArchiver(归档)
  • SQLite
  • CoreData

1. NSUserDefaults

  • NSUserDefaults是object-c语言中的一个单例对象,常用来储存用户相关信息。会存放在目录 Library/Preference下。
  • NSUserDefaults只能存储NSArrayNSDictionaryNSDataNSStringNSNumberNSDate类型。
  • 用法
   //创建
   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
   //NSUserDefaults中有不同类型的存储方式,可以选择对应的方法。
   [defaults setObject:@"李四" forKey:@"name"];
   [defaults setInteger:18 forKey:@"age"];
   
   UIImage *headImg = [UIImage imageNamed:@"img"];
   NSData *data = UIImageJPEGRepresentation(headImg,100);
   [defaults setObject:data forKey:@"headImg"];
   
   //(强制存储)数据同步到文件里,防止意外退出没有存储上
   [defaults synchronize];
   
   //读取
   NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
   NSString *name = [def objectForKey:@"name"];
   NSInteger age = [def integerForKey:@"age"];
   //删除
   [def removeObjectForKey:@"headImg"];
  • 打开沙盒其实会发现在Library/Preferences目录下会生成一个plist文件。NSUserDefaults存储的信息会存储在里面。

2.plist

  • plist存储就是件一个plist文件来存储数据,存储字典与数组。可以用为纯代码创建,还可以用Xcode创建。

    • 代码创建
    /*** 写入 ***/
    //获取沙盒文件目录
     NSString *path= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    
    //拼接路径,这一步,沙盒中并不会存在`123.plist`文件
     NSString *fileName = [path stringByAppendingPathComponent:@ "123.plist" ];
     
     NSDictionary*dict =@{@"age":@18,@"name":@"李四"};
     
    //写入后,再次打开沙盒会发现有了`123.plist`文件
    [dict writeToFile:fileName atomically:YES];
    
    /*** 读取 ***/
    //获取`plist`路径
     NSFileManager * defaultManager = [NSFileManager defaultManager];
     NSURL * documentPath = [[defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]firstObject];
     NSString * fileSavePath = [documentPath.path stringByAppendingPathComponent:@"123.plist"];

   //存的是字典用字典读取,存的是数组用数组读取
     NSDictionary * dic = [NSDictionary dictionaryWithContentsOfFile:fileSavePath];
    
  • XCode创建,这样创建会存在软件包里,沙盒下并没有

    1.New File


    1.png

    2.Property List


    2.png

    3.写入
    3.png

    4.读取

    //获取路径
    NSString *plistPath = [[NSBundle mainBundle]pathForResource:@"propretyText" ofType:@"plist"];
    NSMutableDictionary *dataDic = [[NSMutableDictionary alloc]initWithContentsOfFile:plistPath];
    
    

3.NSKeyedArchiver(归档)

  • NSKeyedArchiver默认只能对NSDate, NSNumber, NSString, NSArray, NSDictionary来进行归档。如果相对对象进行归档需要满足NSCoding协议。
    @interface Person : NSObject<NSCoding>

    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, copy) NSString *age;
    @property (nonatomic, copy) NSString *sex;

    @end

    @implementation Person

    - (void)encodeWithCoder:(NSCoder *)aCoder
    {
     //强调 如果是子类,继承了其他类,父类也要遵循协议执行下面代码
     //[super encodeWithCode:encode]
    
     //编码
     [aCoder encodeObject:self.name forKey:@"name"];
      [aCoder encodeObject:self.age forKey:@"age"];
      [aCoder encodeObject:self.sex forKey:@"sex"];
}

    - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
    {
    //强调 如果是子类,继承了其他类,父类也要遵循协议执行下面代码
    //self = [super initWithCoder:decoder]
    
    
    //解码
      if (self = [super init])
     {
         self.name = [aDecoder decodeObjectForKey:@"name"];
         self.age = [aDecoder decodeObjectForKey:@"age"];
         self.sex = [aDecoder decodeObjectForKey:@"sex"];
     }
    
        return self;
    }

    @end
  • 使用
     Person *p = [[Person alloc] init];
     p.name = @"王三口";
     p.age = @"12";
     p.sex = @"男";
    
    //写入
     NSString *file =  [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
     [NSKeyedArchiver archiveRootObject:p toFile:file];
    
    //读取
     NSString *filePath =  [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
     Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
  • 结果


    11.png

4.SQLite3

FMDB一个很好的管理SQLite的第三方库。FMDB使用可以参考 https://www.jianshu.com/p/54e74ce87404

  • 用sqlite3首选需要导入到项目中


    22.png

*代码

  //打开路径
    NSString *fileName = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"text.sqlite"];
    
    //创建(打开)数据库 (如果数据库不存在,会自动创建)
    int result = sqlite3_open(fileName.UTF8String, &_db);
    
    //表示打开数据库成功
    if (result == SQLITE_OK) {
        
        const char *sql = "create table if not exists person (sex text, name text, age integer);";
        
        char *error = NULL;//错误信息
        
//         sqlite3_exec()可以执行任何SQL语句,比如创表、更新、插入和删除操作。
        int tableResult = sqlite3_exec(_db, sql, NULL, NULL, &error);
        
        //sqlite3_prepare_v2检测SQL语句的合法性,用于查询
//        sqlite3_stmt *stmt = NULL;//定义一个stmt存放结果集
//        int tableResult = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
        
        //增删改查都需要判断
        if (tableResult == SQLITE_OK) {
            NSLog(@"成功表创建");
        }else {
            NSLog(@"创建失败:%s",error);
        }
        
    }

5.CoreData

  • CoreData提供了一种“对象-关系映射”的功能,能将OC对象转化成数据,保存Sqlite中。能够合理管理内存,避免sql语句的麻烦。
    • 1.新建项目勾选 use core data


      33.png
    • 2.创建表


      55.png
    • 3.创建属性


      66.png
    • 4.创建关联的实体对象


      77.png

本编是作者君第一次发文,希望能帮大家。还有一点就是通过这样来巩固一下自己的知识。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容