如何使用 NSCoding 保存结构

Posted

技术标签:

【中文标题】如何使用 NSCoding 保存结构【英文标题】:How to save a struct with NSCoding 【发布时间】:2017-10-18 17:21:27 【问题描述】:

如何使用 NSCoding 保存我的结构,这样即使用户使用它也不会改变 关闭应用程序?如果您也能告诉我如何正确实现缺失的代码,我将不胜感激。

使用以下两个新功能进行更新: 这是我的代码:

    struct RandomItems: Codable

    var items : [String]
    var seen  = 0

    init(items:[String], seen: Int)
    
        self.items = items
        self.seen = seen
    

    init(_ items:[String])
     self.init(items: items, seen: 0) 


    mutating func next() -> String
    
        let index = Int(arc4random_uniform(UInt32(items.count - seen)))
        let item  = items.remove(at:index)
        items.append(item)
        seen = (seen + 1) % items.count
        return item
    
    func toPropertyList() -> [String: Any] 
        return [
            "items": items,
            "seen": seen
        ]
    


    





override func viewWillDisappear(_ animated: Bool) 
    UserDefaults.standard.set(try? PropertyListEncoder().encode(quotes), forKey:"quote2")


override func viewDidAppear(_ animated: Bool) 
     if let data = UserDefaults.standard.value(forKey:"quote2") as? Data 
        let quote3 = try? PropertyListDecoder().decode(Array<RandomItems>.self, from: data)
    






  


extension QuotesViewController.RandomItems 
init?(propertyList: [String: Any]) 
    return nil



如何确保此处覆盖整个 Array?

【问题讨论】:

你需要把它变成一个类。您还需要继承 NSObject 并使其符合 NSCoding Save struct in class to NSUserDefaults using Swift的可能重复 【参考方案1】:

对于结构,您应该使用新的Codable 协议。它从 swift 4 开始可用,强烈推荐。

struct RandomItems: Codable

    var items: [String]
    var seen = 0


extension RandomItems 
     init?(propertyList: [String: Any]) 
           ...
     


// Example usage
let a = RandomItems(items: ["hello"], seen: 2)
let data: Data = try! JSONEncoder().encode(a)
UserDefaults.standard.set(data, forKey: "MyKey") // Save data to disk
// some time passes
let data2: Data = UserDefaults.standard.data(forKey: "MyKey")! // fetch data from disk
let b = try! JSONDecoder().decode(RandomItems.self, from: data2)

更新

看起来原始海报将结构嵌套在另一个类中。这是嵌套结构的另一个示例。

class QuotesViewController: UIViewController 

    struct RandomItems: Codable
    
        var items: [String]
        var seen = 0
    


extension QuotesViewController.RandomItems 
    init(_ items:[String])
         self.items = items 

    init?(propertyList: [String: Any]) 
        guard let items = propertyList["items"] as? [String] else  return nil 
        guard let seen = propertyList["seen"] as? Int else  return nil 
        self.items = items
        self.seen = seen
    


// example usage
let a = QuotesViewController.RandomItems(items: ["hello"], seen: 2)
let data: Data = try! JSONEncoder().encode(a)
UserDefaults.standard.set(data, forKey: "MyKey") // Save data to disk
// some time passes
let data2: Data = UserDefaults.standard.data(forKey: "MyKey")! // fetch data from disk
let b = try! JSONDecoder().decode(QuotesViewController.RandomItems.self, from: data2)

【讨论】:

我必须在哪里插入带有变量声明的三行? @Calimari328 @JoyLucas 我不确定我是否理解您的问题。能改一下吗? let a = .... //错误:无法使用类型为 '(items: [String], seen: Int)' 的参数列表调用类型 'QuotesViewController.RandomItems' 的初始化程序 @Calimari328我该如何解决这个问题? 好吧,也许你的结构需要正确的访问修饰符,或者你需要实现一个公共初始化器。或者,也许您正在向您的结构中添加不可编码的类型。很难用这么少的信息来判断,也不知道您是如何尝试使用它的。 你的结构是什么样的?

以上是关于如何使用 NSCoding 保存结构的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSCoding 保存结构的 Helperclass

如何归档 NSDictionary 的 NSArray(使用 NSCoding)?

如何对 NSCoding 进行单元测试?

无法通过 NSCoding 保存表数据

Objective-C:如何让它为 NSCoding 保存两个文件而不是一个文件?

我如何保存在 NSFileManager 中?