国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【iOS】iOS持久化

這篇具有很好參考價(jià)值的文章主要介紹了【iOS】iOS持久化。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1 持久化目的

  1. 快速展示,提升體驗(yàn)
    • 已經(jīng)加載過(guò)的數(shù)據(jù),用戶下次查看時(shí),不需要再次從網(wǎng)絡(luò)(磁盤)加載,直接展示給用戶
  2. 節(jié)省用戶流量(節(jié)省服務(wù)器資源)
    • 對(duì)于較大的資源數(shù)據(jù)進(jìn)行緩存,下次展示無(wú)需下載消耗流量
    • 同時(shí)降低了服務(wù)器的訪問(wèn)次數(shù),節(jié)約服務(wù)器資源。(圖片)
  3. 離線使用。
    • 用戶瀏覽過(guò)的數(shù)據(jù)無(wú)需聯(lián)網(wǎng),可以再次查看。
    • 部分功能使用解除對(duì)網(wǎng)絡(luò)的依賴。(百度離線地圖、圖書閱讀器)
    • 無(wú)網(wǎng)絡(luò)時(shí),允許用戶進(jìn)行操作,等到下次聯(lián)網(wǎng)時(shí)同步到服務(wù)端。
  4. 記錄用戶操作
    • 草稿:對(duì)于用戶需要花費(fèi)較大成本進(jìn)行的操作,對(duì)用戶的每個(gè)步驟進(jìn)行緩存,用戶中斷操作后,下次用戶操作時(shí)直接繼續(xù)上次的操作。
    • 已讀內(nèi)容標(biāo)記緩存,幫助用戶識(shí)別哪些已讀。
    • 搜索記錄緩存

2 數(shù)據(jù)持久化方式分類

2.1 內(nèi)存緩存

  • 定義
    對(duì)于使用頻率比較高的數(shù)據(jù),從網(wǎng)絡(luò)或者磁盤加載數(shù)據(jù)到內(nèi)存以后,使用后并不馬上銷毀,下次使用時(shí)直接從內(nèi)存加載。
  • 案例
    iOS系統(tǒng)圖片加載——[UIImage imageNamed:@"imageName"]
    網(wǎng)絡(luò)圖片加載三方庫(kù):SDWebImage
  • 實(shí)現(xiàn)
    實(shí)現(xiàn)內(nèi)存緩存的技術(shù)手段包括蘋果官方提供的NSURLCache,NSCache,還有性能和API上比較有優(yōu)勢(shì)的開(kāi)源緩存庫(kù)YYCache、PINCache等。

2.2 磁盤緩存

  • 定義
    將從網(wǎng)絡(luò)加載的、用戶操作產(chǎn)生的數(shù)據(jù)寫入到磁盤,用戶下次查看、繼續(xù)操作時(shí),直接從磁盤加載使用。
  • 案例
    用戶輸入內(nèi)容草稿緩存(如:評(píng)論、文本編輯)
    網(wǎng)絡(luò)圖片加載三方庫(kù):SDWebImage
    搜索歷史緩存
  • 實(shí)現(xiàn)
    1. NSUserDefault
      適合小規(guī)模數(shù)據(jù),弱業(yè)務(wù)相關(guān)數(shù)據(jù)的緩存。
    2. keychain
      Keychain是蘋果提供的帶有可逆加密的存儲(chǔ)機(jī)制,普遍用在各種存用戶名、密碼的需求上。另外,Keychain是系統(tǒng)級(jí)存儲(chǔ),還可以被iCloud同步,即使App被刪除,Keychain數(shù)據(jù)依然保留,用戶下次安裝App,可以直接讀取,通常會(huì)用來(lái)存儲(chǔ)用戶唯一標(biāo)識(shí)串。所以需要加密、同步iCloud的敏感小數(shù)據(jù),一般使用Keychain存取。
    3. 文件存儲(chǔ)
      • Plist:一般結(jié)構(gòu)化的數(shù)據(jù)可以Plist的方式去持久化
      • archiveArchive方式可以存取遵循協(xié)議的數(shù)據(jù),比較方便的是存取使用的都是對(duì)象,不過(guò)中間的序列化和反序列化需要花費(fèi)一定的性能,可以在想要使用對(duì)象直接進(jìn)行磁盤存取時(shí)使用。
      • Stream:指文件存儲(chǔ),一般用來(lái)存圖片、視頻文件等數(shù)據(jù)
    4. 數(shù)據(jù)庫(kù)存儲(chǔ)
      數(shù)據(jù)庫(kù)適合存取一些關(guān)系型的數(shù)據(jù);可以在有大量的條件查詢排序類需求時(shí)使用。
      • Core Data:蘋果官方封裝的ORM(Object Relational Mapping)
      • FMDBgithub最受歡迎的iOS sqlite 封裝開(kāi)源庫(kù)之一
      • WCDB:微信團(tuán)隊(duì)在自己使用的sqlite封裝基礎(chǔ)上的開(kāi)源實(shí)現(xiàn),具有ORM(Object Relational Mapping)的特性,支持iOS、Android。
      • Realm:由Y Combinator孵化的創(chuàng)業(yè)團(tuán)隊(duì)開(kāi)源出來(lái)的一款跨平臺(tái)(iOSAndroid)移動(dòng)數(shù)據(jù)庫(kù)。

2.3 應(yīng)該用哪種緩存方案

根據(jù)需求選擇:

  • 簡(jiǎn)單數(shù)據(jù)存儲(chǔ)直接寫文件、key-value存取即可。
  • 需要按照一些條件查找、排序等需求的,可以使用sqlite等關(guān)系型存儲(chǔ)方式。
  • 不希望App刪除后清除的小容量數(shù)據(jù)(用戶名、密碼、token)存keychain。

3 沙盒機(jī)制介紹

iOS中的沙盒機(jī)制是一種安全體系。為了保證系統(tǒng)安全,iOS每個(gè)應(yīng)用程序在安裝時(shí),會(huì)創(chuàng)建屬于自己的沙盒文件(存儲(chǔ)空間)。應(yīng)用程序只能訪問(wèn)自身的沙盒文件,不能訪問(wèn)其他應(yīng)用程序的沙盒文件,當(dāng)應(yīng)用程序需要向外部請(qǐng)求或接收數(shù)據(jù)時(shí),都需要經(jīng)過(guò)權(quán)限認(rèn)證,否則,無(wú)法獲取到數(shù)據(jù)。所有的非代碼文件都要保存在此,例如屬性文件plist、文本文件、圖像、圖標(biāo)、媒體資源等。

3.1 沙盒機(jī)制與持久化的關(guān)系

iOS 中的持久化是指將數(shù)據(jù)在應(yīng)用程序退出后仍然保留在存儲(chǔ)設(shè)備上的能力。而沙盒機(jī)制是 iOS 系統(tǒng)為每個(gè)應(yīng)用程序提供的安全性措施,通過(guò)將每個(gè)應(yīng)用程序限制在自己的沙盒中,確保應(yīng)用程序只能訪問(wèn)自己的數(shù)據(jù),并不能訪問(wèn)其他應(yīng)用程序的數(shù)據(jù)。

持久化和沙盒機(jī)制在 iOS 應(yīng)用程序中是密切相關(guān)的,因?yàn)閼?yīng)用程序需要在沙盒中對(duì)數(shù)據(jù)進(jìn)行持久化。iOS 提供了幾種方式來(lái)實(shí)現(xiàn)數(shù)據(jù)持久化,而所有這些方式都是在應(yīng)用程序的沙盒內(nèi)進(jìn)行的。以下是 iOS 持久化與沙盒機(jī)制的關(guān)系:

  • 文件儲(chǔ)存持久化: 在 iOS 應(yīng)用程序中,可以使用文件系統(tǒng)來(lái)持久化數(shù)據(jù),例如將數(shù)據(jù)保存到文件中。iOS 應(yīng)用程序只能在自己的沙盒目錄中創(chuàng)建、讀取和寫入文件,不能訪問(wèn)其他應(yīng)用程序的文件。常見(jiàn)的文件系統(tǒng)持久化方式包括使用 NSFileManager 類進(jìn)行文件操作,或者使用 NSDataNSString 類的方法將數(shù)據(jù)寫入文件。
  • UserDefaults 持久化: NSUserDefaults 是一種簡(jiǎn)單的持久化方式,可以用于保存用戶的偏好設(shè)置、配置信息等。雖然數(shù)據(jù)是持久化的,但是它們?nèi)匀淮鎯?chǔ)在應(yīng)用程序的沙盒中,并且只能被當(dāng)前應(yīng)用程序訪問(wèn)。
  • 數(shù)據(jù)庫(kù)持久化:它將數(shù)據(jù)保存到 SQLite 數(shù)據(jù)庫(kù)中或其他數(shù)據(jù)存儲(chǔ)。這些也是在應(yīng)用程序的沙盒內(nèi)進(jìn)行數(shù)據(jù)持久化的方式。
  • Keychain 持久化: KeychainiOS 提供的一種安全存儲(chǔ)敏感數(shù)據(jù)的方式,例如密碼、密鑰等。Keychain 中的數(shù)據(jù)也是在應(yīng)用程序的沙盒內(nèi)進(jìn)行持久化,并且具有更高的安全性保護(hù),確保只有應(yīng)用程序本身才能訪問(wèn)這些數(shù)據(jù)。

總的來(lái)說(shuō),iOS中的持久化操作都是在應(yīng)用程序的沙盒內(nèi)進(jìn)行的,受到沙盒機(jī)制的限制,確保應(yīng)用程序只能訪問(wèn)自己的數(shù)據(jù),保證了應(yīng)用程序之間的數(shù)據(jù)隔離和安全性。

3.2 沙盒的目錄結(jié)構(gòu)

3.2.1 獲取應(yīng)用程序的沙盒路徑:

// 獲取沙盒根目錄路徑
    NSString *path = NSHomeDirectory();

注意: 每次編譯代碼會(huì)生成新的沙盒路徑,注意是編譯不是啟動(dòng),所以模擬機(jī)或者真機(jī)運(yùn)行,每次運(yùn)行所得到的沙盒路徑都是不一樣的,線上版本app真機(jī)不會(huì)生成新的沙盒路徑。

上面的代碼得到的就是當(dāng)前應(yīng)用程序目錄的路徑,該目錄下就是應(yīng)用程序的沙盒,在該目錄下有4個(gè)文件夾:Documents、Library、SystemData、tmp,當(dāng)前應(yīng)用程序只能訪問(wèn)該目錄下的文件。
【iOS】iOS持久化,ios,cocoa,macos

3.2.2 訪問(wèn)沙盒目錄常用C函數(shù)介紹

//文件路徑搜索
FOUNDATION_EXPORT NSArray<NSString *> *NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);

該方法返回值為一個(gè)數(shù)組,在iphone中由于只有一個(gè)唯一路徑,所以直接取數(shù)組第一個(gè)元素即可。

該函數(shù)的作用是返回指定搜索目錄下的路徑數(shù)組。它接受三個(gè)參數(shù):

  1. directoryNSSearchPathDirectory 類型的枚舉值,用于指定搜索的目錄。常見(jiàn)的枚舉值包括:
//常用的NSSearchPathDirectory枚舉值
typedef NS_ENUM(NSUInteger, NSSearchPathDirectory) {
    NSApplicationDirectory = 1,             // supported applications (Applications)
    NSDemoApplicationDirectory,             // unsupported applications, demonstration versions (Demos)
    NSAdminApplicationDirectory,            // system and network administration applications (Administration)
    NSLibraryDirectory,                     // various documentation, support, and configuration files, resources (Library)
    NSUserDirectory,                        // user home directories (Users)
    NSDocumentationDirectory,               //  Library 下的(Documentation)模擬器上沒(méi)有創(chuàng)建
    NSDocumentDirectory,                    // documents (Documents)
};
  1. domainMaskNSSearchPathDomainMask 類型的位掩碼,用于指定搜索路徑的范圍。常見(jiàn)的枚舉值包括:
typedef NS_OPTIONS(NSUInteger, NSSearchPathDomainMask) {
    NSUserDomainMask = 1,       // 用戶目錄 - 基本上就用這個(gè)。 
    NSLocalDomainMask = 2,      // 本地
    NSNetworkDomainMask = 4,    // 網(wǎng)絡(luò) 
    NSSystemDomainMask = 8,     // 系統(tǒng)
    NSAllDomainsMask = 0x0ffff  // 所有 
};
  1. expandTildeBOOL 類型的參數(shù),指定是否展開(kāi)波浪號(hào)~。如果設(shè)置為 YES,則路徑中的波浪號(hào)~將被展開(kāi)為用戶的主目錄路徑。

該值為NO:Caches目錄路徑為~/Library/Caches
該值為YES:Caches目錄路徑為/var/mobile/Containers/Data/Application/E7B438D4-0AB3-49D0-9C2C-B84AF67C752B/Library/Caches

3.2.3 沙盒目錄的獲取示例

//獲取沙盒根路徑
NSString *path = NSHomeDirectory();
NSLog(@"沙盒根路徑:%@", path);
//Document路徑
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSLog(@"Document目錄路徑:%@", docDir);
// 獲取Library的目錄路徑
NSString *libDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"Libarary目錄路徑:%@", libDir);
// 獲取Caches目錄路徑
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
NSLog(@"Cacheas目錄路徑:%@", cachesDir);
// library Preference
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSLog(@"偏好設(shè)置目錄路徑:%@", defaults);
// 獲取tmp目錄路徑
NSString *tmpDir =  NSTemporaryDirectory();
NSLog(@"tmp目錄路徑:%@", tmpDir);

輸出結(jié)果:
【iOS】iOS持久化,ios,cocoa,macos

3.2.4 沙盒目錄介紹

  • Documents:保存持久化數(shù)據(jù),會(huì)備份。一般用來(lái)存儲(chǔ)需要持久化的數(shù)據(jù)。
    一般我們?cè)陧?xiàng)目中,我們會(huì)把一些用戶的登錄信息以及搜索歷史記錄等一些關(guān)鍵數(shù)據(jù)存儲(chǔ)到這里。
// 獲取Documents目錄路徑
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

此文件夾是默認(rèn)備份的,備份到iCloud。
注:iCloud的備份,會(huì)通過(guò)Wi-Fi每天自動(dòng)備份用戶iOS設(shè)備。
我們可以在獲取到的路徑結(jié)尾加一個(gè)字符串來(lái)創(chuàng)建一個(gè)文件名:

NSString *filename = [docDir stringByAppendingPathComponent:@"data.txt"];

這樣我們的這個(gè)filename就是一個(gè)完整的.txt類型文件的目錄了。

  • Library:默認(rèn)存放設(shè)置和其他狀態(tài)信息,除了caches子目錄之外其他目錄都會(huì)被iclude同步。
    • Application Support:此目錄包含應(yīng)用程序用來(lái)運(yùn)行但應(yīng)對(duì)用戶隱藏的文件,如游戲的新關(guān)卡等文件。
    • Caches:保存應(yīng)用運(yùn)行時(shí)生成的需要持久化的數(shù)據(jù),一般存儲(chǔ)體積大、不需要備份的非重要數(shù)據(jù),如網(wǎng)絡(luò)請(qǐng)求的音視頻與圖片等的緩存。在 iOS 5.0 及以后版本中,Caches 當(dāng)系統(tǒng)磁盤空間非常低時(shí),系統(tǒng)可能會(huì)在極少數(shù)情況下該刪除目錄(APP 正在運(yùn)行時(shí)不會(huì)發(fā)生),所以盡量保證該路徑的文件在 APP 在重新運(yùn)行時(shí)可以得到重新創(chuàng)建。
    • Cooikes:系統(tǒng)會(huì)自動(dòng)將App中網(wǎng)絡(luò)請(qǐng)求的cookie保存為文件。
    • Preferences:保存應(yīng)用的所有偏好設(shè)置。UserDefaults 生成的 plist 文件就會(huì)保存該目錄下。
    • SplashBoard:存儲(chǔ)啟動(dòng)屏緩存,緩存文件格式為 ktx,本質(zhì)上就是圖片,如果啟動(dòng)屏不生效的問(wèn)題可以考慮從刪除該路徑下相關(guān)緩存文件這個(gè)角度解決。
  • SystemData:存放系統(tǒng)數(shù)據(jù),無(wú)對(duì)外暴露的接口。
  • tmp:臨時(shí)文件夾(系統(tǒng)會(huì)不定期刪除里面的文件)。

4 持久化數(shù)據(jù)存儲(chǔ)方式

4.1 plist文件(序列化)

plist文件是通過(guò)XML文件的方式保存在目錄中 以下類型可以被序列化:

NSString;//字符串
NSMutableString;//可變字符串
NSArray;//數(shù)組
NSMutableArray;//可變數(shù)組
NSDictionary;//字典
NSMutableDictionary;//可變字典
NSData;//二進(jìn)制數(shù)據(jù)
NSMutableData;//可變二進(jìn)制數(shù)據(jù)
NSNumber;//基本數(shù)據(jù)
NSDate;//日期

這里我們就用NSDictionary當(dāng)例子,其他的類型和這個(gè)方法類似:

- (void) writeToPlist {
    // 定義plistName
    NSString *plistName = @"test.plist";
    // 存取路徑
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    // 打印路徑
    NSLog(@"%@", path);
    // 連接路徑
    NSString *filePath = [path stringByAppendingPathComponent:plistName];
    
    // 定義字典文件
    NSDictionary *dict = @{@"SXTTTTT":@"10"};
    
    //序列化
    [dict writeToFile:filePath atomically:YES];
}

atomically是否先寫入輔助文件,增加安全性的寫入文件方法,一般都是YES。

前往打印出的路徑查看,發(fā)現(xiàn)確實(shí)多了一個(gè)test.plist文件。
【iOS】iOS持久化,ios,cocoa,macos

打開(kāi)這個(gè)文件看看。
【iOS】iOS持久化,ios,cocoa,macos

可以看到值確實(shí)儲(chǔ)存到了這個(gè)文件內(nèi)部。

使用dictionaryWithContentsOfFile:類方法可以取出這個(gè)值:

    NSDictionary *dict1 = [NSDictionary dictionaryWithContentsOfFile:filePath];
    NSLog(@"%@", dict1);

結(jié)果:
【iOS】iOS持久化,ios,cocoa,macos

4.2 preference:偏好設(shè)置

偏好設(shè)置(Preferences)是 iOS 開(kāi)發(fā)中一種簡(jiǎn)單的數(shù)據(jù)持久化方式,用于保存應(yīng)用程序的配置信息、用戶偏好設(shè)置等數(shù)據(jù)。在 iOS 中,可以使用 NSUserDefaults 類來(lái)進(jìn)行偏好設(shè)置的讀取和保存。

NSUserDefaults 是一個(gè)單例類,用于訪問(wèn)應(yīng)用程序的偏好設(shè)置。它可以存儲(chǔ)各種類型的數(shù)據(jù),如布爾值、整數(shù)、浮點(diǎn)數(shù)、字符串、數(shù)組、字典等。這些數(shù)據(jù)將會(huì)持久化到應(yīng)用程序的沙盒中,即使應(yīng)用程序退出,下次啟動(dòng)時(shí)也可以讀取這些數(shù)據(jù)。

NSUserDefaults:簡(jiǎn)單數(shù)據(jù)快速讀寫,不能存儲(chǔ)自定義類型。
UserDefaults設(shè)置數(shù)據(jù)時(shí),不是立即寫入,而是根據(jù)時(shí)間戳定時(shí)地把緩存中的數(shù)據(jù)寫入本地磁盤。所以調(diào)用了set方法之后數(shù)據(jù)有可能還沒(méi)有寫入磁盤應(yīng)用程序就終止了。出現(xiàn)以上問(wèn)題,可以通過(guò)調(diào)用synchornize方法[defaults synchornize];強(qiáng)制寫入。

偏好設(shè)置存儲(chǔ)的優(yōu)點(diǎn):

  • 不需要關(guān)心文件名,系統(tǒng)會(huì)自動(dòng)幫你生成一個(gè)文件名。
  • 快速做鍵值對(duì)的存儲(chǔ)。

我們來(lái)嘗試使用使用UserDefaults注冊(cè)一個(gè)賬號(hào)密碼

- (void)writeToUserDefaults {
    // 獲取偏好設(shè)置對(duì)象
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
    // 存儲(chǔ)數(shù)據(jù)
    [defaults setObject:@"ouhaijian" forKey:@"name"];
    [defaults setObject:@"666666" forKey:@"password"];
    
    // 同步調(diào)用,立刻寫到文件中,不寫這個(gè)方法會(huì)異步,有延遲
    [defaults synchronize];
}
- (void)readFromUserDefaults {
    // 獲取偏好設(shè)置對(duì)象
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
    // 獲取數(shù)據(jù)
    NSString *name = [defaults objectForKey:@"name"];
    NSString *password = [defaults objectForKey:@"password"];
    
    NSLog(@"name:%@", name);
    NSLog(@"password:%@", password);
}

運(yùn)行結(jié)果:
【iOS】iOS持久化,ios,cocoa,macos

注意,對(duì)于設(shè)置偏好設(shè)置值后,需要調(diào)用 synchronize 方法來(lái)立即將數(shù)據(jù)保存到磁盤中,以確保數(shù)據(jù)持久化。不過(guò),iOS 7 及以上版本,synchronize 方法會(huì)自動(dòng)在合適的時(shí)機(jī)將數(shù)據(jù)保存,所以不再是必需的操作。

我們到cd到沙盒中的preference文件目錄,可以看到里面多了一個(gè)新的文件,這個(gè)文件里面儲(chǔ)存的就是我們儲(chǔ)存的賬號(hào)。
【iOS】iOS持久化,ios,cocoa,macos

打開(kāi)這個(gè)文件看看。
【iOS】iOS持久化,ios,cocoa,macos

4.3 NSKeyedArchiver歸檔和解檔

NSKeyedArchiver(歸檔):歸檔一般都是保存自定義對(duì)象的時(shí)候,使用歸檔。因?yàn)?code>plist文件不能夠保存自定義對(duì)象。如果一個(gè)字典中保存有自定義對(duì)象,如果把這個(gè)對(duì)象寫入到文件當(dāng)中,它是不會(huì)生成 plist文件的。如果對(duì)象是NSString、NSDictionary、NSArray、NSDataNSNumber等類型,可以直接用NSKeyedArchiver進(jìn)行歸檔和恢復(fù)。

但是在我們使用歸檔之前,我們必須得遵守NSSecureCoding協(xié)議才行,老版本只需要遵循NSCoding實(shí)現(xiàn)其歸檔和解檔的方法就行,但是iOS13更新之后就不行了,我們就必須的遵守NSSecureCoding協(xié)議,NSSecureCoding協(xié)議也遵循了原來(lái)NSCoding這個(gè)協(xié)議,不過(guò)我們還需要遵循它的一個(gè)supportsSecureCoding方法,這樣我們才能歸檔成功。

因?yàn)?code>NSSecureCoding協(xié)議也遵循了原來(lái)NSCoding這個(gè)協(xié)議,所以他也就有了- (void)encodeWithCoder:(NSCoder *)coder方法和- (id)initWithCoder:(NSCoder *)coder方法:

-(void)encodeWithCoder:(NSCoder *)coder,每次歸檔對(duì)象時(shí),都會(huì)調(diào)用這個(gè)方法。一般在這個(gè)方法里面指定如何歸檔對(duì)象中的每個(gè)實(shí)例變量??梢允褂胑ncodeObject:forKey:方法歸檔實(shí)例變量。

-(id)initWithCoder:(NSCoder *)coder,每次從文件中會(huì)恢復(fù)(解碼)對(duì)象時(shí),都會(huì)調(diào)用這個(gè)方法。一般在這個(gè)方法里面指定如何解碼文件中的數(shù)據(jù)為對(duì)象的實(shí)例變量,可以使用decodeObject:forKey方法解碼實(shí)例變量。

例,新建一個(gè)SXPerson類:

#import <Foundation/Foundation.h>

@interface SXPerson : NSObject <NSSecureCoding>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@end

@implementation SXPerson
- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:self.name forKey:@"name"];
    [coder encodeInt:self.age forKey:@"age"];
}

- (id)initWithCoder:(NSCoder *)coder {
    if (self = [super init]) {
        self.name = [coder decodeObjectForKey:@"name"];
        self.age = [coder decodeIntForKey:@"age"];
    }
    return self;
}

+ (BOOL)supportsSecureCoding {
    return YES;
}
@end

進(jìn)行歸檔和解檔:

// 歸檔
- (void)writeUseNSKeyedArchiver {
    SXPerson *person = [[SXPerson alloc] init];
    person.age = 10;
    person.name = @"蔡徐坤";
    NSError * __autoreleasing *error = NULL;
    
    // 獲得Document的全路徑
    NSString *docu = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    // 獲得新文件的全路徑
    NSString *path = [docu stringByAppendingPathComponent:@"SXPerson.data"];
    // 將對(duì)象封裝為Data并歸檔
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:error];
    if (error) {
        NSLog(@"writeUseNSKeyedArchiver:%@", *error);
    } else {
        [data writeToFile:path atomically:YES];
    }
}

// 解檔
- (void)readUseNSKeyedArchiver {
    NSError * __autoreleasing *error = NULL;
    // 獲得Document的全路徑
    NSString *docu = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    // 獲得新文件的全路徑
    NSString *path = [docu stringByAppendingPathComponent:@"SXPerson.data"];
    // 從path路徑中獲取data數(shù)據(jù)
    NSData *unData = [NSData dataWithContentsOfFile:path];
    // 創(chuàng)建解檔操作的客戶端允許的類集合
        // 這個(gè)集合應(yīng)包括自定義對(duì)象的屬性的類
    NSSet *allowedClassesSet = [NSSet setWithObjects:[NSString class], [SXPerson class], nil];
    SXPerson *person = (SXPerson *)[NSKeyedUnarchiver unarchivedObjectOfClasses:allowedClassesSet fromData:unData error:error];
    // 打印結(jié)果
    if (error) {
        NSLog(@"readUseNSKeyedArchiver:%@", *error);
    } else {
        NSLog(@"%@-%d", person.name, person.age);
    }
}

創(chuàng)建解檔操作的客戶端允許的類集合,這個(gè)集合應(yīng)包括自定義對(duì)象的屬性的類,否則會(huì)給出警告。這個(gè)警告并不會(huì)導(dǎo)致解檔操作出錯(cuò),但是在將來(lái)的版本中可能會(huì)被禁止。為了避免將來(lái)的兼容性問(wèn)題,建議您在解檔時(shí)將需要解檔的所有類都添加到客戶端允許的類集合中。

結(jié)果:
【iOS】iOS持久化,ios,cocoa,macos

我們還可以看到Document目錄下多了一個(gè)SXStudent.data文件:
【iOS】iOS持久化,ios,cocoa,macos

可以使用vim打開(kāi)這個(gè)文件看一下,大概能看懂是儲(chǔ)存了NSKeyedArchiver歸檔的一個(gè)對(duì)象:
【iOS】iOS持久化,ios,cocoa,macos

最后另外說(shuō)一點(diǎn),歸檔操作有時(shí)會(huì)被用于實(shí)現(xiàn)對(duì)象(尤其是自定義對(duì)象)的深拷貝操作。通過(guò)歸檔,我們可以將原對(duì)象序列化為二進(jìn)制數(shù)據(jù),并在反歸檔時(shí)重新創(chuàng)建出一個(gè)全新的對(duì)象,包括其內(nèi)部引用對(duì)象。這樣,新對(duì)象與原對(duì)象之間是完全獨(dú)立的,修改其中一個(gè)對(duì)象不會(huì)影響到另一個(gè)對(duì)象。

4.4 數(shù)據(jù)庫(kù)存儲(chǔ)(這部分太多了,以后有機(jī)會(huì)另學(xué))

  • SQLite
    是目前主流的嵌入式關(guān)系型數(shù)據(jù)庫(kù),其最主要的特點(diǎn)就是輕量級(jí)、跨平臺(tái),當(dāng)前很多嵌入式操作系統(tǒng)都將其作為數(shù)據(jù)庫(kù)首選。
  • CoreData
    CoreData是iOS5之后才出現(xiàn)的一個(gè)框架,本質(zhì)上是對(duì)SQLite的一個(gè)封裝,它提供了對(duì)象-關(guān)系映射(ORM)的功能,即能夠?qū)C對(duì)象轉(zhuǎn)化成數(shù)據(jù),保存在SQLite數(shù)據(jù)庫(kù)文件中,也能夠?qū)⒈4嬖跀?shù)據(jù)庫(kù)中的數(shù)據(jù)還原成OC對(duì)象,在這個(gè)過(guò)程中不需要手動(dòng)編寫任何SQL語(yǔ)句,CoreData封裝了數(shù)據(jù)庫(kù)的操作過(guò)程,以及數(shù)據(jù)庫(kù)中數(shù)據(jù)和OC對(duì)象的轉(zhuǎn)換過(guò)程。通過(guò)CoreData管理應(yīng)用程序的數(shù)據(jù)模型,可以極大程度減少需要編寫的代碼數(shù)量。
  • FMDB
    是一個(gè)處理數(shù)據(jù)存儲(chǔ)的第三方框架,框架是對(duì)sqlite的封裝,整個(gè)框架非常輕量級(jí)但又不失靈活性,而且更加面向?qū)ο蟆?/li>
  • SQLiteCoreData的區(qū)別:
    CoreData可以在一個(gè)對(duì)象更新時(shí),其關(guān)聯(lián)的對(duì)象也會(huì)隨著更新,相當(dāng)于你更新一張表時(shí),其關(guān)聯(lián)的其他表的也會(huì)隨著更新。
    CoreData供更簡(jiǎn)單的性能管理機(jī)制,可以限制查詢記錄的總數(shù),這個(gè)類會(huì)自動(dòng)更新其緩存。
    多表查詢方面,CoreData沒(méi)有SQL直觀,沒(méi)有類似外連接,左連接等操作。

5 補(bǔ)充

5.1 什么是序列化和反序列化,用來(lái)做什么?

  • 序列化:把對(duì)象轉(zhuǎn)化為字節(jié)序列的過(guò)程
  • 反序列化:把字節(jié)序列恢復(fù)成對(duì)象
  • 作用:把對(duì)象寫到文件或者數(shù)據(jù)庫(kù)中,并且讀取出來(lái)

5.2 程序中的plist文件

plist全名Property List,屬性列表文件,它是一種用來(lái)存儲(chǔ)串行化后的對(duì)象的文件,屬性列表文件的擴(kuò)展名為plist ,因此通常被稱為plist文件。文件是xml格式的。

這里補(bǔ)充一下程序中的plist文件,及其對(duì)應(yīng)的寫入,讀取操作。

程序中的plist文件必須先創(chuàng)建,后使用:
【iOS】iOS持久化,ios,cocoa,macos

源代碼:

// 寫入程序plist
- (void)setDataToPlist {
    // 第一參數(shù):文件名
    // 第二參數(shù):文件后綴
    NSString *plist = [[NSBundle mainBundle] pathForResource:@"show" ofType:@"plist"];
    NSDictionary *dict = @{@"蔡徐坤":@"name", @10:@"age"};
    [dict writeToFile:plist atomically:YES];
}

// 讀取程序plist
- (void)getDataFromPlist {
    NSString *plist = [[NSBundle mainBundle] pathForResource:@"show" ofType:@"plist"];
    NSLog(@"%@", plist);
    NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:plist];
    NSLog(@"%@", dict);
}

運(yùn)行結(jié)果:
【iOS】iOS持久化,ios,cocoa,macos

雖然我們?cè)陧?xiàng)目工程里創(chuàng)建了這個(gè)文件,但是數(shù)據(jù)似乎并不會(huì)保存在這個(gè)文件里,至少不是這個(gè)工程包里的文件。

我們cd到打印出來(lái)的目錄中:
【iOS】iOS持久化,ios,cocoa,macos

使用vim看看這個(gè)同名文件:
【iOS】iOS持久化,ios,cocoa,macos

可以看到數(shù)據(jù)被保存到應(yīng)用程序的資源束(Resource Bundle)中。

當(dāng)我們編譯項(xiàng)目時(shí),Xcode似乎會(huì)將資源文件(包括 .plist 文件)全復(fù)制到應(yīng)用程序的資源束(Resource Bundle)中。這樣可以確保在運(yùn)行時(shí)能夠找到并正確讀取資源文件中的內(nèi)容。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-612465.html

到了這里,關(guān)于【iOS】iOS持久化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Redis兩種持久化方案RDB持久化和AOF持久化

    Redis兩種持久化方案RDB持久化和AOF持久化

    Redis持久化 Redis有兩種持久化方案: RDB持久化 AOF持久化 1.1.RDB持久化 RDB全稱Redis Database Backup file(Redis數(shù)據(jù)備份文件),也被叫做Redis數(shù)據(jù)快照。簡(jiǎn)單來(lái)說(shuō)就是把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤中。當(dāng)Redis實(shí)例故障重啟后,從磁盤讀取快照文件,恢復(fù)數(shù)據(jù)??煺瘴募Q為RDB文件

    2024年02月14日
    瀏覽(28)
  • redis持久化【RDB+AOF】持久化雙雄

    redis持久化【RDB+AOF】持久化雙雄

    這是redis系列文章之《redis持久化【RDB+AOF】持久化雙雄》,上一篇文章【redis基礎(chǔ)】redis的十大數(shù)據(jù)類型_努力努力再努力mlx的博客-CSDN博客 感謝大家的支持~ 目錄 RDB 什么是RDB RDB的作用 配置文件關(guān)于RDB部分? 6vs7 操作步驟 修改配置文件(本案例設(shè)置5s修改2次) 修改dump文件的保

    2024年02月08日
    瀏覽(48)
  • RabbitMQ系列(8)--實(shí)現(xiàn)RabbitMQ隊(duì)列持久化及消息持久化

    RabbitMQ系列(8)--實(shí)現(xiàn)RabbitMQ隊(duì)列持久化及消息持久化

    概念:在上一章文章中我們演示了消費(fèi)者宕機(jī)的情況下消息沒(méi)有被消費(fèi)成功后會(huì)重新入隊(duì),然后再被消費(fèi),但如何保障RabbitMQ服務(wù)停掉的情況下,生產(chǎn)者發(fā)過(guò)來(lái)的消息不會(huì)丟失,這時(shí)候我們?yōu)榱讼⒉粫?huì)丟失就需要將隊(duì)列和消息都標(biāo)記為持久化。 1、實(shí)現(xiàn)RabbitMQ隊(duì)列持久化 只需

    2024年02月09日
    瀏覽(22)
  • 全面解析 Redis 持久化:RDB、AOF與混合持久化

    前言: 每次你在游戲中看到玩家排行榜,或者在音樂(lè)應(yīng)用中瀏覽熱門歌單,有沒(méi)有想過(guò)這個(gè)排行榜是如何做到實(shí)時(shí)更新的?當(dāng)然,依靠 Redis 即可做到。 在技術(shù)領(lǐng)域,我們經(jīng)常聽(tīng)到 「鍵值存儲(chǔ)」 這個(gè)詞。但在 Redis 的世界里,這只是冰山一角。Redis 的對(duì)象,不僅僅是簡(jiǎn)單的數(shù)據(jù)

    2024年03月10日
    瀏覽(33)
  • Redis 持久化-RDB和 持久化-AOF 的詳細(xì)介紹以及區(qū)別

    Redis 持久化-RDB和 持久化-AOF 的詳細(xì)介紹以及區(qū)別

    在線文檔: https://redis.io/topics/persistence RDB(Redis DataBase) AOF(Append Of File) 在指定的時(shí)間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤, 也就Snapshot 快照,恢復(fù)時(shí)將快照文件讀到內(nèi)存 RDB 及其執(zhí)行流程 對(duì)上圖的解讀 具體流程如下: redis 客戶端執(zhí)行bgsave 命令或者自動(dòng)觸發(fā)bgsave 命令;

    2024年02月09日
    瀏覽(32)
  • RabbitMQ-數(shù)據(jù)持久化

    1、交換機(jī)持久化(SpringAMQP默認(rèn)) 2、隊(duì)列持久化(SpringAMQP默認(rèn)) 3、消息持久化 ? ? ? ? 如果采用純內(nèi)存操作,那么消息存儲(chǔ)達(dá)到隊(duì)列的上限之后,會(huì)有一個(gè)page out操作,這個(gè)操作是將隊(duì)列中已經(jīng)有的一部分MQ消息轉(zhuǎn)移到磁盤,給隊(duì)列騰出空間,使得隊(duì)列能夠繼續(xù)接收MQ消息

    2024年01月21日
    瀏覽(23)
  • Redis 持久化

    Redis 持久化

    默認(rèn)情況下,redis 工作時(shí)所有數(shù)據(jù)都是存儲(chǔ)于內(nèi)存中的,不論是否有磁盤上的持久化數(shù)據(jù),都是工作于內(nèi)存當(dāng)中,redis 本身就是一個(gè)內(nèi)存的數(shù)據(jù)庫(kù),如果 redis 崩潰或斷電導(dǎo)致所有數(shù)據(jù)丟失,所以 redis 提供了持久化功能來(lái)保證數(shù)據(jù)的可靠性, redis 持久化有兩種實(shí)現(xiàn):RDB 和 A

    2024年01月18日
    瀏覽(11)
  • 12.redis 持久化

    12.redis 持久化

    redis 是一個(gè)內(nèi)存數(shù)據(jù)庫(kù),把數(shù)據(jù)存儲(chǔ)在內(nèi)存中的,內(nèi)存中的數(shù)據(jù)是不持久的,要想做到持久,就需要讓redis把數(shù)據(jù)存儲(chǔ)到硬盤上。 為了保證速度塊,數(shù)據(jù)肯定還是得在內(nèi)存中,但是為了持久化,數(shù)據(jù)還得想辦法存儲(chǔ)在硬盤上。 RDB = Redis DataBase 定期備份 RDB 定期的把 Redis 內(nèi)存中

    2024年02月09日
    瀏覽(21)
  • Docker 持久化

    Docker 持久化

    為了能夠保存(持久化)數(shù)據(jù)以及共享容器間的數(shù)據(jù), Docker 提出了 Volume 的概念。簡(jiǎn)單來(lái)說(shuō), Volume 就是目錄或者文件,它可以 繞過(guò) 默認(rèn)的聯(lián)合文件系統(tǒng),而以正常的文件或者目錄的形式存在于宿主機(jī)上。 數(shù)據(jù)卷方式: 數(shù)據(jù)卷是一個(gè)特殊的文件或者目錄,它將宿主機(jī)文件或

    2024年02月03日
    瀏覽(22)
  • Redis持久化

    Redis持久化

    Redis持久化 實(shí)現(xiàn)類似照片記錄效果的方式,就是 把某一時(shí)刻的數(shù)據(jù)和狀態(tài)以文件的形式寫到磁盤上,也就是快照 。這樣一來(lái)即使故障宕機(jī),快照文件也不會(huì)丟失,數(shù)據(jù)的可靠性也就得到了保證。這個(gè)快照文件就稱為RDB文件( dump.rdb ),其中,RDB就是Redis DataBase的縮寫。 在指定

    2024年02月03日
    瀏覽(18)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包