NSUserDefaults 歸檔

一、歸檔的基本概念

之前將數(shù)據(jù)保存本地,只能是字符串、數(shù)組、字典、NSNuber、BOOL等容器類(lèi)對(duì)象對(duì)象,不能將所有對(duì)象都給保存,而采用歸檔能將所有的對(duì)象轉(zhuǎn)化為二進(jìn)制數(shù)據(jù)保存在文件中,并通過(guò)解歸檔讓將文件里面保存的數(shù)據(jù)讀取出來(lái)

二、使用環(huán)境

之前我們給通訊錄添加一個(gè)聯(lián)系人只能是將添加的人放到一個(gè)字典中,然后將這個(gè)字典放到數(shù)組中,最終將數(shù)組寫(xiě)入文件中

當(dāng)我們需要顯示這些聯(lián)系人時(shí),要從文件中將這個(gè)數(shù)組讀取出來(lái),還要將數(shù)據(jù)里面的一個(gè)個(gè)字典轉(zhuǎn)化成model,放到一個(gè)新數(shù)組里

而現(xiàn)在我們可以使用歸檔在添加的時(shí)候就將這一個(gè)個(gè)聯(lián)系人的信息轉(zhuǎn)化成model,將這些model直接放到一個(gè)數(shù)組里,需要展示的時(shí)候,在從文件中讀取出來(lái)數(shù)據(jù),此時(shí)這個(gè)數(shù)組里面存放直接就是一個(gè)個(gè)model

有些應(yīng)用支持一個(gè)離線(xiàn)緩存,也就是說(shuō)當(dāng)手機(jī)沒(méi)聯(lián)網(wǎng)時(shí),可以將手機(jī)有網(wǎng)時(shí)的數(shù)據(jù)存放在本地,當(dāng)手機(jī)沒(méi)網(wǎng)時(shí),從本地中取出來(lái)這些數(shù)據(jù)展示

三、某個(gè)對(duì)象支持歸檔解歸檔需要滿(mǎn)足三個(gè)條件

1、所屬的類(lèi)遵守NSCoding協(xié)議

2、實(shí)現(xiàn)協(xié)議里面的歸檔方法

  - (void)encodeWithCoder:(NSCoder *)aCoder

3、實(shí)現(xiàn)協(xié)議里面的解歸檔方法

  - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder

四、對(duì)系統(tǒng)的類(lèi)進(jìn)行歸檔解歸檔

1、指定將對(duì)象放在哪個(gè)文件中,歸檔后的文件,后綴要求是archiver

   [NSHomeDirectory() stringByAppendingPathComponent:@"data.archiver"];

2、將對(duì)象歸檔到指定的路徑中

   [NSKeyedArchiver archiveRootObject:name toFile:path];

3、將歸檔后的數(shù)據(jù)提取出來(lái)

   [NSKeyedUnarchiver unarchiveObjectWithFile:path];

五、對(duì)自定義的類(lèi)進(jìn)行歸檔與解歸檔

1、讓這個(gè)類(lèi)遵循<NSCoding>

2、實(shí)現(xiàn)歸檔方法,aCoder就是歸檔時(shí)傳過(guò)來(lái)的歸檔對(duì)象,對(duì)象被歸檔時(shí)會(huì)調(diào)用這個(gè)方法

  - (void)encodeWithCoder:(NSCoder *)aCoder{

     [aCoder encodeObject:self.name forKey:@"name"];

     [aCoder encodeInteger:self.age forKey:@"age"];

     [aCoder encodeObject:self.sex forKey:@"sex"];
  }


3、實(shí)現(xiàn)解歸檔方法,對(duì)象解歸檔是會(huì)調(diào)用這個(gè)方法

  - (instancetype)initWithCoder:(NSCoder *)aDecoder{

   //解歸檔時(shí)會(huì)產(chǎn)生一個(gè)Person對(duì)象,這里是給這個(gè)Person對(duì)象賦值
   self = [super init];
  
   if (self) {
    
     self.name = [aDecoder decodeObjectForKey:@"name"];

     self.age = [aDecoder decodeIntegerForKey:@"age"];

     self.sex = [aDecoder decodeObjectForKey:@"sex"];
   }

     return self;
 }

六、同時(shí)將多個(gè)對(duì)象歸檔與解歸檔

1、歸檔

  1)準(zhǔn)備一個(gè)可變的data對(duì)象,通過(guò)歸檔對(duì)象將多個(gè)數(shù)據(jù)存在一個(gè)data對(duì)象里,最終將這個(gè)data寫(xiě)入文件

    NSMutableData *data = [NSMutableData data];

  2)archiver初始化的時(shí)候包裝一個(gè)可變的data對(duì)象

    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];

  3)通過(guò)歸檔對(duì)象將這些數(shù)據(jù)轉(zhuǎn)化成二進(jìn)制,并保存在一個(gè)data對(duì)象里

    [archiver encodeObject:name forKey:@"name"];

    [archiver encodeInteger:age forKey:@"age"];

    [archiver encodeObject:sex forKey:@"sex"];

  4)轉(zhuǎn)化完畢,意思是結(jié)束使用歸檔對(duì)象將上面的數(shù)據(jù)保存在了data里面

    [archiver finishEncoding];

  5)將轉(zhuǎn)化好的data寫(xiě)入文件

    [data writeToFile:path atomically:YES];

2、解歸檔

  1)將路徑里的二進(jìn)制數(shù)據(jù)給取出來(lái)
    
    NSMutableData *data = [NSMutableData dataWithContentsOfFile:path];

  2)將二進(jìn)制數(shù)據(jù)包裝在一個(gè)解歸檔對(duì)象中

    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];

  3)通過(guò)解歸檔對(duì)象將二進(jìn)制數(shù)據(jù)分別給反序列化

    NSString *name = [unarchiver decodeObjectForKey:@"name"];

    NSInteger age = [unarchiver decodeIntegerForKey:@"age"];

    NSString *sex = [unarchiver decodeObjectForKey:@"sex"];

一、基本概念

1、之前如果我們想要實(shí)現(xiàn)一個(gè)對(duì)象支持整個(gè)應(yīng)用程序訪(fǎng)問(wèn),需要自己創(chuàng)建一個(gè)單例對(duì)象,而其實(shí)iOS系統(tǒng)內(nèi)部給我們提供了這個(gè)一個(gè)單例類(lèi),NSUserDefaults,用來(lái)保存一些整個(gè)應(yīng)用程序都能訪(fǎng)問(wèn)到的數(shù)據(jù)

2、保存到NSUserDefaults對(duì)象的內(nèi)容都被放在沙盒Library/Oreferences文件夾中

3、對(duì)這個(gè)NSUserDefaults對(duì)象進(jìn)行操作,就相當(dāng)于對(duì)文件進(jìn)行操作

4、NSUserDefaults對(duì)象的存取方式和字典類(lèi)似

二、用法

1、通過(guò)單例方法找到NSUserDefault對(duì)象

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

2、用NSUserDefault對(duì)象存儲(chǔ)數(shù)據(jù),因?yàn)閿?shù)據(jù)最終是存放在plist文件中,所以在這里可以存儲(chǔ)plist里面支持的數(shù)據(jù)類(lèi)型,存取方式和字典類(lèi)似

  [defaults setInteger:12 forKey:@"age"];

3、用NSUserDefault對(duì)象取數(shù)據(jù)

  [defaults integerForKey:@"age"];

4、用NSUserDefault對(duì)象移除偏好設(shè)置里面的數(shù)據(jù)

  [defaults removeObjectForKey:nil];

三、宏定義與NSUserDefault的搭配使用

1、存值

 #define kSaveMyDefault(A,B) [[NSUserDefaults standardUserDefaults] setObject:B forKey:A]

2、取值

 #define kFetchMyDefault(A) [[NSUserDefaults standardUserDefaults] objectForKey:A]

四、練習(xí)

1、應(yīng)用第一次啟動(dòng)有新手教程

 1) 打開(kāi)模擬本地緩存的工程

 2)創(chuàng)建繼承與UIViewController的控制器FirstLaunchViewController,用來(lái)做歡迎界面,.m文件如下


   #import "FirstLaunchViewController.h"
   #import "AppDelegate.h"
   @interface FirstLaunchViewController ()

   @end

   @implementation FirstLaunchViewController

   - (void)viewDidLoad {
     [super viewDidLoad];

      self.view.backgroundColor = [UIColor whiteColor];

      UILabel *welcomeLabel = [[UILabel alloc]initWithFrame:self.view.frame];

      welcomeLabel.text = @"歡迎您";
      welcomeLabel.font = [UIFont boldSystemFontOfSize:20];
      welcomeLabel.textAlignment = NSTextAlignmentCenter;
      [self.view addSubview:welcomeLabel];
     }

     - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

       //獲取到應(yīng)用程序的appDelegate
       AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
       
       //在AppDelegate方法內(nèi)給重新設(shè)置window的主窗口
       [appDelegate setWindowRootVC];

     }
   @end

 3)AppDelegate.h

   #import <UIKit/UIKit.h>

   @interface AppDelegate : UIResponder <UIApplicationDelegate>

   @property (strong, nonatomic) UIWindow *window;

   //聲明一個(gè)用來(lái)切換window主窗口的window
   - (void)setWindowRootVC;

   @end

 4) 修改AppDelegate.m的內(nèi)容如下

   #import "AppDelegate.h"
   #import "ViewController.h"
   #import "FirstLaunchViewController.h"

   //通過(guò)宏定義讓偏好設(shè)置存取值
   #define kSaveMyDefault(A,B) [[NSUserDefaults standardUserDefaults] setObject:B forKey:A]

   #define kFetchMyDefault(A) [[NSUserDefaults standardUserDefaults] objectForKey:A]

   @interface AppDelegate ()

   @end

   @implementation AppDelegate

   - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

   self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
   [self.window makeKeyAndVisible];

   //設(shè)置window的根控制器
   [self setWindowRootVC];

    return YES;
   }

   - (void)setWindowRootVC{

    //判斷之前是否啟動(dòng)過(guò)
    if (kFetchMyDefault(@"isFirst") == nil) {
    
      //如果沒(méi)有啟動(dòng)過(guò)就給鍵isFirst賦值
      kSaveMyDefault(@"isFirst", @1);
    
      FirstLaunchViewController *firstLaunchVC = [[FirstLaunchViewController alloc]init];
    
      self.window.rootViewController = firstLaunchVC;
    
      }else {
    
        self.window.rootViewController = [[UINavigationController alloc]initWithRootViewController:[[ViewController alloc]init]];
      }

   }

   @end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容