从NSUserDefaults检索自定义对象

时间:2019-09-17 22:42:45

标签: ios swift userdefaults

我有一个值字典

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

我将其中的一部分转变成自定义对象并显示在表格视图中。

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

然后用户可以选择两个对象存储在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()

但是这会打印出来

  

(功能)

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

1 个答案:

答案 0 :(得分:2)

第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: $0) }) else {
        return nil
    }
    self = value
  }
  func json() -> [String:Any] {
    return (try? JSONEncoder().encode(self))
      .flatMap { try? JSONSerialization.jsonObject(with: $0, 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: $0) }) else {
        return nil
    }
    self = value
  }
  func json() -> [String:Any] {
    return (try? JSONEncoder().encode(self))
      .flatMap { try? JSONSerialization.jsonObject(with: $0, 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") ?? [:]))