ios本地存儲字典
A. iOS開發之數據存儲以及刪除
iOS本地數據保存有多種方式,歸納如下:
本章不僅是學習多種數據存儲方式,也可學習到其他知識點,下面就讓我們詳細來看:
具體方培梁核法為:
第一步:獲得文件即將保存的路徑,並生成在該路徑下的文件:
第二步:往文件中寫入/讀取:
方法一:
方法配掘二:
方法三:
2.NSUserDefaults:是一個單例對象,在整個應用程序的生命周期中都只有一個實例。用渣旅來保存應用程序設置和屬性、用戶保存的數據。存儲在沙盒的Library/Preference中,NSUserDefaults可以存儲的數據類型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。寫入和讀取都比較簡單,如下:
寫入:
NSString *str = [userDefault objectForKey:@"gang"];
@interface Person : NSObject <NSCoding>//遵守NSCoding協議
@property (nonatomic,strong) NSString *name;
@property (nonatomic,assign) NSInteger age;
@end
解檔操作:
同樣調用NSCoder子類NSKeyedArchiver的方法unarchiveRootObject:toFile: 即可
[NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archiver encodeObject:person forKey:@"person"];
[archiver encodeObject:bir forKey:@"bir"];
// 存檔完畢(一定要調用這個方法)
[archiver finishEncoding];
[data writeToFile:path atomically:YES];
NSData *undata = [NSData dataWithContentsOfFile:path];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
[unarchiver decodeObjectForKey:@"person"];
[unarchiver decodeObjectForKey:@"bir"];
// 恢復完畢
[unarchiver finishDecoding];
B. iOS數據存儲(一)介紹
iOS本地化存儲的數據保存在沙盒中。
(1) Documents :iTunes會備份該目錄。一般用來存儲需要持久化的數據。
(2) Library/Caches :緩存,iTunes不會備份該目錄。內存不足時會被清除,應用沒有運行時,可能會被清除。一般存儲體積大、不需要備份的非重要數據。
(3) Library/Preference :iTunes同會備份該目錄,可以用來存儲一些偏好設置。
(4) tmp : iTunes不會備份這個目錄,用來保存臨時數據,應用退出時會清除該目錄下的數據。
獲取沙盒文件:
其中:
可以把字典或數組直接寫入到文件中。另外, NSString 、 NSData 、 NSNumber 等類型,也可以使用 writeToFile:atomically: 方法直接將對象寫入文件中,只是 Type 為空。
NSUserDefaults是輕量級存儲,一般使用它來進行一些設置的記錄,比如用戶ID,開關是否打開等設置,通過鍵值對的方式記錄設置,所以這個有時候也被稱為偏好設置。
NSUserDefaults可以存儲的數據類型包括: NSData 、 NSString 、 NSNumber 、 NSDate 、 NSArray 、 NSDictionary 。如果要存儲其他類型,則需要轉換為前面的類型,才能用NSUserDefaults存儲。
也可以寫成宏定義
C. iOS存儲技術-Keychain
鑰匙串這個技術大家每天都在用,它相當於一個容器,裡面有已加密的和未加密的用戶信息,它是怎麼實現安全儲存Mac、App、伺服器和網站的帳戶,開發過程中又該怎麼使用這個技術呢。通過一個例子來介紹一下:
用戶要登錄你的APP,這個時候用戶在文本框輸入了他的用戶信息和密碼,那麼你該如何存儲這個信息?自然我們會有一個類似用戶的結構來存儲用戶信息
這個結構里有一個String類型的用戶名稱和一個String類型的密碼變數, 張三輸入了它自己的用戶名「zhangsan」和密碼「******」來登陸,那麼我們就會有一個生成用戶的過程
那麼接下來你希望存儲到Keychain中,Keychain有哪些方法呢?第一步自然是添加
函數有三個參數,但是每個似乎都不認識,所以我們先簡單看一下這三個參數要做什麼
第一個參數是個字典,那自然是由許多key-value構成,首先它要包含一個這個數據的類型,數據類型使用kSecClass來做key,kSecClass的定義:
可以看到kSecClass是一個CFString類型的全局變數,它其中可用的值由Item Class Keys and Values列出。根據數據類型的不同有不同的值,例如密碼、認證,對於密碼它的值定義為:
也是一個CFString類型的變數, class對應的值會決定數據是否被加密,當選擇這個password的時候數據就會被加密。那麼我們字典中的第一個key-value對就有了:
那麼這個字典還需要包含什麼呢? 賬號:也就是這個數據是誰的數據,這個屬性由kSecAttrAccount這個Key來定義,同樣它也是一個CFString類型的Key,它的值是你自定義的一個CFString類型的值。當然這個屬性並不是必須的,於是字典中的第二個key-value對也有了
⚠️注意
字典中除了用戶名還需要用戶的數據,數據使用kSecValueData這個Key來定義,同樣是CFString類型的Key,但是用戶的數據可能多種多樣,所以它的值類型是CFData。那麼就需要把用戶的信息加工一下
這樣就得到了字典中第三個key-value對:
既然是鑰匙串,那就不能隨時隨地訪問,需要訪問控制許可權,所謂訪問控制就是你希望當iPhone解鎖的時候,或者是驗證了用戶的指紋之後才能繼續進行的過程。許可權由kSecAttrAccessControl這個Key來表示,它所對應的值是一個SecAccessControl的實例,而SecAccessControl又是什麼?
它就是一個包含Keychain對象怎麼被使用的信息的一個不透明類型,來看看它的實例化
它通過(CFAllocatorRef allocator, CFTypeRef protection, SecAccessControlCreateFlags flags, CFErrorRef _Nullable *error)函數來創建
函數有四個參數:
1.第一個參數是用來初始化SecAccessControlRef對象的. 我們可以傳 NULL 或者kCFAllocatorDefault
2.第二個參數是控制設備什麼情況下可以訪問這個Keychain信息, 它的值可以是添加Keychain函數的第一個參數字典中的一個其它key(kSecAttrAccessible)對應的值,例如可以控制當設備解鎖的時候使用的值:: CFString。其它可使用的還有(只有這台設備且設置了密碼)、(只有這個設備第一次解鎖後)。
3.第三個參數是一組額外的訪問控制:用來控制用戶級別的訪問許可權,如果設備沒有密碼總是處於unlocked的狀態,你可能希望進一步限制KeyChain訪問。例如在獲取銀行賬戶的認證時候,需要在獲取認證信息之前驗證是不是授權用戶在操作,這使得KeyChain可以根據用戶的輸入來管理對Keychain的訪問,可以選擇devicePasscode來限制需要用戶需要輸入密碼或者是選擇userPresence來讓系統根據當前狀態選擇一種驗證方式或者是多種方式的組合
第四個是失敗原因的一個指針,這里暫時傳一個nil值
所以我們可以通過來獲得一個訪問控制的參數
⚠️注意
現在我們可以回到之前創建函數的第一個參數字典的分析了,我們得到了
SecAccessControl的實例,所以字典的第四個key-value對也有了:
現在字典中有了數據的類型、哪個用戶的數據、用戶要存儲的數據、什麼條件可以訪問這個數據。看起來不缺少什麼了。我們的一個字典參數就處理好了:
函數會通過第二個參數來返回新添加的Keychain,具體的類型是根據第一個參數中指定的返回類型決定的(例如可以通過kSecReturnData這個可以指定返回類型為CFData) 當然,通常我們可以忽略這個返回的數據,所以可以傳一個nil值
函數還有一個返回值,從聲明上看是一個OSStatus類型的值,相應的定義在Security Framework Result Codes中,常見的值有:
我們通常需要將返回值和已知的返回值相比較來判斷是否操作成功了,也就是我們通常可以使用如下的語句來處理添加操作
至此,添加操作就完成了。
查詢主要使用SecItemCopyMatching(CFDictionaryRef query, CFTypeRef _Nullable *result)函數,函數會返回一個或者多個item,或者是指定的item屬性的,默認情況下只會返回匹配的第一個結果。
函數的第一個參數就是和添加Keychain函數的參數一樣的結構,通常有Keychain的class也就是由kSecClass為Key的一個key-value對。
屬性:屬性就是Keychain結果需要符合的條件,例如想查找哪個用戶的數據,查詢參數還可以帶控制返回的key,因為添加方法和查詢方法都會返回結果的數據和屬性到提供的參數指針里,所以可以指定返回的key來控制指針對應的返回數據的格式,也就是通常的密碼查詢應該包含kSecReturnData為Key的key-value對。
例如可以使用kSecReturnPersistentRef這個Key來獲得一個CFData的引用,然後可以把它存儲在磁碟或在進程間傳遞,可以在這之後調用另一個SecItemCopyMatching函數將持久化引用轉為常規引用,函數參數里需要將持久化的引用的數組作為kSecMatchItemList的值傳入。如果使用kSecReturnData來控制返回data本身,搜索會返回一個代表實際數據的CFData,這個就是典型的密碼Keychain的使用方式。同時,Keychain服務會在返回給你之前對數據進行解密
搜索參數:這個參數可以包含一些結果的數量條件,控制string屬性是否大小寫敏感等。
所以,希望查詢上面的用戶信息的時候查詢字典參數會如下所示
函數的第二個參數是一個CFTypeRef類型的接收函數返回的指針,我們需要先定義一個這樣的指針:
同樣我們需要判斷函數返回值是否成功:
因為查詢字典參數里攜帶了kSecReturnData,所以這個指針指向的數據類型是一個CFData類型的參數,我們需要獲取對應的值
這樣 str就是我們之前存儲在KeyChain中的用戶信息了
至此,Keychain的添加和刪除都已經具備了,基本的用戶需求就解決了。
除了基礎的使用之外,我們還可以
這些,下次再說吧