NSCoding & Codable & NSKeyedArchiver

緩存符合NSCoding協(xié)議的任意對(duì)象
- (void)encodeWithCoder:(NSCoder *)coder;
- (nullable instancetype)initWithCoder:(NSCoder *)coder; // NS_DESIGNATED_INITIALIZER
example
override func encode(with coder: NSCoder) {
  super.encode(with: coder)
}

required init?(coder: NSCoder) {
  super.init(coder: coder)
}

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
  super.init(nibName: nibNameOrNil, bundle: nil)
}

convenience init() {
  self.init(nibName: nil, bundle: nil)
}

override func viewDidAppear(_ animated: Bool) {
  super.viewDidAppear(animated)
  if YAuth.isLoggedIn {
    interactor.getMessageCount()
  }
  if let libraryPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).last {
    let directory = libraryPath + "/archiver_directory"
    if !FileManager.default.fileExists(atPath: directory) {
      try? FileManager.default.createDirectory(atPath: directory, withIntermediateDirectories: true, attributes: nil)
    }
    let data = NSMutableData()
    let archiver = NSKeyedArchiver(forWritingWith: data)
    archiver.encode(UIViewController(), forKey: "archiver_key")
    archiver.finishEncoding()
    data.write(to: URL.init(fileURLWithPath: directory + "/file_name"), atomically: true)
  }
  
  GCDQueue.executeInMainQueue({
    if let libraryPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).last {
      let directory = libraryPath + "/archiver_directory"
      if let data = NSData(contentsOfFile: directory + "/file_name") as Data? {
        let unarchiver =  NSKeyedUnarchiver.init(forReadingWith: data)
        if let vc = unarchiver.decodeObject(forKey: "archiver_key") as? UIViewController {
          self.present(vc, animated: true, completion: nil)
        }
      }
    }
  }, afterDelay: .seconds(10))
}

Codable協(xié)議

typealias Codable = Decodable & Encodable

public protocol Decodable {
    init(from decoder: Decoder) throws
}

public protocol Encodable {
    func encode(to encoder: Encoder) throws
}

JSONEncoder

struct GroceryProduct: Codable {
  var name: String
  var points: Int
  var description: String?
}

let pear = GroceryProduct(name: "Pear", points: 250, description: "A ripe pear.")

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

let data = try encoder.encode(pear)
print(String(data: data, encoding: .utf8)!)

/* Prints:
 {
   "name" : "Pear",
   "points" : 250,
   "description" : "A ripe pear."
 }
*/

JSONDecoder

struct GroceryProduct: Codable {
   var name: String
   var points: Int
  var description: String?
}
let json = """
{
    "name": "Durian",
    "points": 600,
    "description": "A fruit with a distinctive scent."
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let product = try decoder.decode(GroceryProduct.self, from: json)

print(product.name) // Prints "Durian"

自定義嵌入鍵

class User: Codable {
  
  var name: String?
  
  // 自定義嵌入鍵
  enum CodingKeys: String, CodingKey {
    case memberName
  }
  
  required init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    name = try container.decode(String.self, forKey: .memberName)
  }
  
  func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(name, forKey: .memberName)
  }

  init() {
    
  }
}

let jsonData = """
{
  "memberName": "Janine",
}
""".data(using: .utf8)!


func test() {
  do {
    let user = try? JSONDecoder().decode(User.self, from: jsonData)
    let data = try? JSONEncoder().encode(user)
    print(user.debugDescription)
    print(data?.description)
  } catch {
    print(error.localizedDescription)
  }
}

NSCoding & NSKeyedArchiver & Data Parsing

#import "DataModel.h"
#import <objc/runtime.h>

@implementation DataModel

- (NSArray *)getAllPropertyNames       //獲取類的所有屬性名稱
{
    u_int count;
    objc_property_t *properties  =class_copyPropertyList([self class], &count);
    NSMutableArray *propertiesArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        const char* propertyName =property_getName(properties[i]);
        [propertiesArray addObject: [NSString stringWithUTF8String: propertyName]];
    }
    free(properties);
    return propertiesArray;
}

- (id)bundingData:(NSDictionary *)dict{          //綁定數(shù)據(jù)
    static Class oldClass;
    if ([self class]!=oldClass) {
        DLog(@"   >>>>>>>  綁定模型 >>>>>>>>>> : %@\n\n",[self class]);
        oldClass = [self class];
    }
    if (dict==nil) {
        return nil;
    }
    NSArray *propertyNames = [self getAllPropertyNames];
    for (NSString *key in propertyNames) {
        id value = nil;
        if ([key isEqualToString:@"pid"]) {
            value = [dict objectForKeyOrNil:@"id"];
        }else{
            value = [dict objectForKeyOrNil:key];
        }
        if (value) {
            [self setValue:value forKey:key];   //使用KVC給屬性賦值
        }
    }
    return self;
}

- (NSDictionary *)toDictionary{
    NSArray *propertyKeyArray = [self getAllPropertyNames];
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    for (NSString *key in propertyKeyArray) {
        id obj = SafeObj([self valueForKey:key]);
        //對(duì)象為空則不轉(zhuǎn)換到Dictionary中
        if ((NSNull *)obj == [NSNull null]) {
            continue;
        }
        if ([key isEqualToString:@"pid"]) {
            [dict setObject:obj forKey:@"id"];
        }else{
            [dict setObject:obj forKey:key];
        }
    }
    return dict;
}

- (void)clearData{          //清除對(duì)象的值
    //   DLog(@"%@",self);                   //輸出調(diào)試信息
    NSArray *propertyNames = [self getAllPropertyNames];
    for (NSString *key in propertyNames) {
        [self setValue:[NSNull null] forKey:key];   //使用KVC給屬性賦值,清除對(duì)象的值
    }
    DLog(@"清除類 ------ > %@ (%@)",NSStringFromClass([self class]),self);
}


- (NSString *)description               //類描述方法
{
    NSMutableString *desc = [NSMutableString string];
    [desc appendString:@"\n\n"];
    [desc appendFormat:@"Class name: %@\n", NSStringFromClass([self class])];
    NSArray *propertyNames = [self getAllPropertyNames];
    for (NSString *key in propertyNames) {
        [desc appendFormat: @"%@: %@\n", key, [self valueForKey:key]];
    }
    return [NSString stringWithString:desc];
}


#pragma -mark 對(duì)象歸檔協(xié)議<NSCoding>方法
- (void)encodeWithCoder:(NSCoder *)encoder {
    NSArray *propertyNames = [self getAllPropertyNames];
    for (NSString *key in propertyNames) {
        [encoder encodeObject:[self valueForKey:key] forKey:key];
    }
}

- (id)initWithCoder:(NSCoder *)decoder {
    NSArray *propertyNames = [self getAllPropertyNames];
    for (NSString *key in propertyNames) {
        [self setValue:[decoder decodeObjectForKey:key] forKey:key] ;
    }
    return self;
}

#pragma -mark 對(duì)象歸檔
- (void)archiverToFile:(NSString *)fileName{                        //對(duì)象歸檔保存
    NSString *fullPath = [self getDocumentsPath:fileName];
    [NSKeyedArchiver archiveRootObject:self toFile:fullPath];
}

- (id)unArchiverFromFile:(NSString *)fileName{                      //反歸檔對(duì)象
    NSString *fullPath = [self getDocumentsPath:fileName];
    if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath]){
        DataModel *model = [NSKeyedUnarchiver unarchiveObjectWithFile: fullPath];
        return model;
    }else{
        return nil;
    }
}
#pragma -mark 輔助方法
- (NSString *)getDocumentsPath:(NSString *)fileName{          //獲取文檔目錄
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docPath = [paths objectAtIndex:0];
    return [docPath stringByAppendingPathComponent:fileName];
}

@end
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前面文章中 UserDefaults 的基本用法 中對(duì)UserDefaults 進(jìn)行了簡(jiǎn)單的介紹,它可以將一些簡(jiǎn)單...
    JamesSawyer閱讀 4,905評(píng)論 2 12
  • Google question: what is keyed decoding container 翻譯自: ht...
    ngugg閱讀 701評(píng)論 0 1
  • 緩存 在眾多可以本地保存數(shù)據(jù)的技術(shù)中,有三種脫穎而出:URL緩存、數(shù)據(jù)模型緩存(利用NSKeyedArchiver...
    hui8685291閱讀 1,103評(píng)論 0 1
  • 為什么要有緩存 應(yīng)用需要離線工作的主要原因就是改善應(yīng)用所表現(xiàn)出的性能。將應(yīng)用內(nèi)容緩存起來就可以支持離線。我們可以用...
    milk_powder閱讀 2,913評(píng)論 6 24
  • 偶爾當(dāng)心如水面 平靜如冰 坐在風(fēng)景之外看個(gè)不停 懼怕摩天大樓阻擋住天空 怎么走也走不到應(yīng)該去的地方 石子入水 波動(dòng)...
    伍丁零閱讀 317評(píng)論 0 7

友情鏈接更多精彩內(nèi)容