从 NSUserDefaults 检索自定义对象

Retrieving custom Object from NSUserDefaults

我有一本价值观字典

class Objects {
    let values = [
    "AAA": ["AAAAAAA", "111111111"],
    "BBB": ["BBBBBBBB", "2222222"],
    "CCC": ["CCCCCCCC", "3333333333"],
    "DDD": ["DDDDDD", "44444444"],
    ]
}

我将其转换为自定义对象并显示在表格视图中。

struct  Object {
   var heading : String!
   var imageName: String!
}

然后用户可以 select 两个对象存储在 UserDefaults

let defaults = UserDefaults.standard

func addObject(_ object1: String, object2: String) {

    // Get objects for user
    var userObjects = fetchObjectsFromUserDefaults()

    // Add to user currencies
    userObjects.append([object1,object2])

    //Update user defaults value for key
    // [ [Object1, Object2], [Object1, Object2] ]

    defaults.set(userObject, forKey: "userCurrencies")
}

// Gets [[String]] values from user defaults for key
func fetchObjectsFromUserDefaults() -> [[String]] {
    if let objects = UserDefaults.standard.value(forKey: "userObjects") {
        return objects as! [[String]]
    } else {
        return []
    }
}


// Uses [[String]] values and turns them into objects by using the dictionary to determine property values 

func getObject() -> [[Object]] {
    let userObject = fetchObjectsFromUserDefaults()
    // [ [Object1, Object2], [Object1, Object2] ]

    let object = Object()

    var fetchedObject = [[Object]]()

    if !userObjects.isEmpty {
        for c in userObjects {
            var set = [Object]()
            if let val = object.available[c[0]] {
                set.append(Currency(currencyTitle: c[0], imageName: val[0] ))
            }

            if let val2 = object.available[c[1]] {
                set.append(Currency(currencyTitle: c[0], imageName: val2[0] ))
            }

            if !set.isEmpty {
                fetchedObjects.append(set)
            }
        }
        return fetchedObjects
    }

    return [[]]

}

视图控制器

在这里,我将对象加载到 TableView

let fetched = dataManager.getObjects
print(fetched)
self.objects = fetched()

然而这打印出来

(Function)

我哪里做错了,他们是一种更好的存储和检索用户默认数据的方法吗?我觉得这已经结束了,有一种更快捷、更安全的方法。

步骤 1.

制作你的结构Codable。如果 struct 的所有成员都是 Codable,幸运的是 StringCodable,编译器将为您编写所有函数,所以它只是:

struct Object: Codable {
  var heading : String!
  var imageName: String!
}

第 2 步

Codable 的问题在于它与 Data 相互转换,但您想与 Dictionary 相互转换。幸运的是 JSONSerialization 从 Data 转换为 Dictionary 所以创建一个新的协议并给它一个带有协议扩展的默认实现:

protocol JSONRepresentable {
  init?(json: [String: Any])
  func json() -> [String: Any]
}
extension JSONRepresentable where Self: Codable {
  init?(json: [String:Any]) {
    guard let value = (try? JSONSerialization.data(withJSONObject: json, options: []))
      .flatMap ({ try? JSONDecoder().decode(Self.self, from: [=11=]) }) else {
        return nil
    }
    self = value
  }
  func json() -> [String:Any] {
    return (try? JSONEncoder().encode(self))
      .flatMap { try? JSONSerialization.jsonObject(with: [=11=], options: []) } as? [String: Any] ?? [:]
  }
}

步骤 3.

使您的结构符合 JSONRepresentable

struct Object: Codable, JSONRepresentable {
  var heading : String!
  var imageName: String!
}

第 4 步

将您的对象放入 Userdefaults 并再次取出:

let o = Object.init(heading: "s", imageName: "a").json()
UserDefaults.standard.set(o, forKey: "test")
print(Object.init(json: UserDefaults.standard.dictionary(forKey: "test") ?? [:]))

如果你想尝试,这里是整个游乐场:

import UIKit

struct Object: Codable, JSONRepresentable {
  var heading : String!
  var imageName: String!
}

protocol JSONRepresentable {
  init?(json: [String: Any])
  func json() -> [String: Any]
}
extension JSONRepresentable where Self: Codable {
  init?(json: [String:Any]) {
    guard let value = (try? JSONSerialization.data(withJSONObject: json, options: []))
      .flatMap ({ try? JSONDecoder().decode(Self.self, from: [=14=]) }) else {
        return nil
    }
    self = value
  }
  func json() -> [String:Any] {
    return (try? JSONEncoder().encode(self))
      .flatMap { try? JSONSerialization.jsonObject(with: [=14=], options: []) } as? [String: Any] ?? [:]
  }
}

let o = Object.init(heading: "s", imageName: "a").json()
UserDefaults.standard.set(o, forKey: "test")
print(Object.init(json: UserDefaults.standard.dictionary(forKey: "test") ?? [:]))