浅谈IOS数据持久化

IOS本地数据持久化的几种类型、包括应用场景分析

1.NSUserDefault(属性列表)

2.文件(沙盒写入)

3.PList

4.数据库

5.CoreData

6.归档

7.Keychain(钥匙串)


二.应用场景

1,NSUserDefaults

用于存储用户的偏好设置和用户信息,如用户名,是否自动登录,字体大小等.

数据自动保存在沙盒的Libarary/Preferences目录下.

NSUserDefaults将输入的数据储存在.plist格式的文件下,这种存储方式就决定了它的安全性几乎为0,所以不建议存储一些敏感信息如:用户密码,token,加密私钥等!

它能存储的数据类型为:NSNumber(NSInteger、float、double),NSString,NSDate,NSArray,NSDictionary,BOOL.

不支持自定义对象的存储.

NSUserDefaults*userDefault = [NSUserDefaultsstandardUserDefaults];    [userDefault setInteger:1forKey:@"integer"];    [userDefault setBool:YESforKey:@"BOOl"];    [userDefault setFloat:6.5forKey:@"float"];    [userDefault setObject:@"123"forKey:@"numberString"];NSString*numberString = [userDefault objectForKey:@"numberString"];BOOLmyBool = [userDefault boolForKey:@"BOOl"];  [userDefault removeObjectForKey:@"float"];    [userDefault synchronize];

需要注意的问题:

NSUserDefaults存储的数据都是不可变的,想将可变数据存入需要先转为不可变才可以存储.

NSUserDefaults是定时把缓存中的数据写入磁盘的,而不是即时写入,为了防止在写完NSUserDefaults后程序退出导致的数据丢失,可以在写入数据后使用synchronize强制立即将数据写入磁盘.

2,plist

即属性列表文件,全名是Property List,这种文件的扩展名为.plist,因此,通常被叫做plist文件。它是一种用来存储串行化后的对象的文件,用于存储程序中经常用到且数据量小而不经常改动的数据。

可以存储的类型:NSNumber,NSString,NSDate,NSData ,NSArray,NSDictionary,BOOL.

不支持自定义对象的存储.

plist的创建方式有两种:command + n 创建和纯代码创建,不同的创建方式使用方法也自然不同

command + n 创建:

创建:(创建方法自行百度)

读取:

NSString*plistPath = [[NSBundlemainBundle]pathForResource:@"myTest"ofType:@"plist"];NSMutableDictionary*dataDic = [NSMutableDictionarydictionaryWithContentsOfFile:plistPath];/**如果为数组时*

///NSMutableArray *dataArray = [NSMutableArray arrayWithContentsOfFile:plistPath];    NSLog(@"%@",dataDic);

修改:

[dataDic setObject:@"男"forKey:@"sex"];[dataDic setObject:@15forKey:@"age"];[dataDic writeToFile:plistPath atomically:YES];NSLog(@"----%@",dataDic);

纯代码创建:

创建:

NSArray*sandBoxPath =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);NSString*documentsPath = [sandBoxPath objectAtIndex:0];NSString*plistPath = [documentsPath stringByAppendingPathComponent:@"myTestPlist.plist"];NSLog(@"%@",plistPath);

写入:

NSMutableDictionary*dic = [NSMutableDictionarydictionary];[dic setObject:@"18"forKey:@"age"];[dic setObject:@"胡杨"forKey:@"name"];[dic writeToFile:plistPath atomically:YES];

读取:

NSArray*sandBoxPath =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);NSString*documentsPath = [sandBoxPath objectAtIndex:0];NSString*plistPath = [documentsPath stringByAppendingPathComponent:@"myTestPlist.plist"];NSLog(@"%@",plistPath);NSMutableDictionary*dataDic = [NSMutableDictionarydictionaryWithContentsOfFile:plistPath];NSLog(@"-----%@",dataDic);

修改:

与command+n方法相同.

需要注意的问题:

如果需要存储自定义类型的数据需要先进行序列化!

3,Keychain

用于本地重要数据的存储,将数据加密后存储在本地更安全.如:密码,秘钥,序列号等.当你删除APP后Keychain存储的数据不会删除,所以在重装App后,Keychain里的数据还能使用。从ios 3.0开始,跨程序分享keychain变得可行而NSUserDefaults存储的数据会随着APP而删掉.

使用keychain时苹果官方已经为我们封装好了文件KeychainItemWrapper,引入即可使用.当然也可是使用其他优秀的第三方的封装,比如ssKeychain,使用方法如下:

使用方法

4,归档(NSKeyedArchiver)

归档是iOS开发中数据存储常用的技巧,归档可以直接将对象储存成文件,把文件读取成对象。

相对于plist或者userdefault形式,归档可以存储的数据类型更加多样,并且可以存取自定义对象。对象归档的文件是保密的,在磁盘上无法查看文件中的内容,更加安全。

遵守NSCoding协议,并实现该协议中的两个方法。如果是继承,则子类一定要重写那两个方法。因为子类在存取的时候,会去子类中去找调用的方法,没找到那么它就去父类中找,所以最后保存和读取的时候新增加的属性会被忽略。需要先调用父类的方法,先初始化父类的,再初始化子类的。

保存数据的文件的后缀名可以随意命名。

demo

5,沙盒写入

持久化在Document目录下,一般存储非机密数据。当App中涉及到电子书阅读、听音乐、看视频、刷图片列表等时,推荐使用沙盒存储。因为这可以极大的节约用户流量,而且也增强了app的体验效果.

Application:存放程序源文件,上架前经过数字签名,上架后不可修改。

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

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

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

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

// 获取程序的Home目录      NSString*path =NSHomeDirectory();// 获取Document目录      NSString*path =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject;// 获取Cache目录      NSString*path =NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES).firstObject;// 获取Library目录      NSString*path =NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask,YES).firstObject;// 获取Tmp目录      NSString*path =NSTemporaryDirectory();

写入:

NSString*path =NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES).firstObject;NSString*filePath = [path stringByAppendingPathComponent:@"test.txt"];NSLog(@"%@",filePath);NSArray*array = @[@"1",@"2",@"3"];BOOLisSuccess = [array writeToFile:filePath atomically:YES];if(isSuccess) {NSLog(@"成功");    }else{NSLog(@"失败");    }

读取:

NSString*path =NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES).firstObject;NSString*filePath = [path stringByAppendingPathComponent:@"test.txt"];NSLog(@"%@",filePath);NSArray*tmpArray = [NSArrayarrayWithContentsOfFile:filePath];NSLog(@"%@",tmpArray);

6,数据库

适合储存数据量较大的数据,一般使用FMDB和CoreData来实现.

FMDB:

FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API,使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码,对比苹果自带的Core Data框架,更加轻量级和灵活,提供了多线程安全的数据库操作方法,有效地防止数据混乱。

CoreData:

Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句.但是直接操作CoreData显的不是那么容易,所以我多数的时候会使用MagicRecord来实现.MagicRecord是对CoreData的二次封装,使用起来简单操作方便.

FMDB 和 MagicRecord 的 demo

FMDB和MagicRecord的性能方面各有千秋,需要根据项目的实际需求进行选择.没有最好的方案只有最适合的方案!

FMDB与MagicRecord的性能比较

数据迁移:

如果使用到数据库那就不得不提数据迁移的问题,不管是MagicRecord还是FMDB如果要更新数据库都要进行数据迁移.

FMDB的数据迁移:

判断表中有没有这个字段,如果没有使用sq语句插入.

/**添加字段/数据迁移*/- (void)dataMigrationWithTableName:(NSString*)tableName newAdded:(NSString*)newAdded block:(FMDBblock)block{//tableName:表名//newAdded:新加字段名    [_queue inDatabase:^(FMDatabase * _Nonnull db) {if(![db columnExists:newAdded inTableWithName:tableName]){NSString*sql = [NSStringstringWithFormat:@"ALTER TABLE %@ ADD %@ INTEGER",tableName,newAdded];BOOLsuccess = [db executeUpdate:sql];if(success) {                            block(YES,@"字段添加成功");                      }else{                            block(NO,@"字段添加失败");                  }            }      }];}

MagicRecord的数据迁移:

首先在初始化的时候要注意初始化语句.

/**以程序名为数据库名,不需要自动升级*/[MagicalRecord setupCoreDataStack];/**以程序名为数据库名,需要自动升级*/[MagicalRecord setupAutoMigratingCoreDataStack];/**自定义数据库名,不需要自动升级*/[MagicalRecord setupCoreDataStackWithStoreNamed:@"SQDemo.sqlite"];/**自定义数据库名,需要自动升级*/[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"SQDemo.sqlite"];

next 新建一个模型的新版本

image

next 添加新字段并且选择model2为当前模型

image

最后为model2新建实体类就可以了!

原文:https://www.jianshu.com/p/1be31f9f07c6

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

推荐阅读更多精彩内容