淺談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,使用方法如下:
ofollow,noindex">使用方法
4,歸檔(NSKeyedArchiver)
歸檔是iOS開發中資料儲存常用的技巧,歸檔可以直接將物件儲存成檔案,把檔案讀取成物件。
相對於plist或者userdefault形式,歸檔可以儲存的資料型別更加多樣,並且可以存取自定義物件。物件歸檔的檔案是保密的,在磁碟上無法檢視檔案中的內容,更加安全。
遵守NSCoding協議,並實現該協議中的兩個方法。如果是繼承,則子類一定要重寫那兩個方法。因為子類在存取的時候,會去子類中去找呼叫的方法,沒找到那麼它就去父類中找,所以最後儲存和讀取的時候新增加的屬性會被忽略。需要先呼叫父類的方法,先初始化父類的,再初始化子類的。
儲存資料的檔案的字尾名可以隨意命名。
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的二次封裝,使用起來簡單操作方便.
DBAndMagicalRecordDemo.git" target="_blank" rel="nofollow,noindex">FMDB 和 MagicRecord 的 demo
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
作者:隔牆送來鞦韆影
連結:https://www.jianshu.com/p/954a2101cffe
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。