如何使用UserDefaults保存和加载我的结构?

时间:2017-10-22 10:51:44

标签: swift struct save nsuserdefaults codable

我是编程新手。我已经创建了一个Codable类型,但我不知道我必须在函数viewWillDisappear中放置什么,其中结构应该保存到UserDefaults以及我必须放在函数viewDidAppear,其中应该再次显示保存的结构。

到目前为止,这是我的代码:

import UIKit



class QuotesViewController: UIViewController {

var randomItems: RandomItems?


var quotes: RandomItems! = RandomItems([

   "Andre",
   "James",
   "Max",
   "Stephen",
   "Sarah",
   "Jeff",
   "Paul",
   "Mary",
                          ])




}

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 viewDidLoad() {
    let defaults = UserDefaults.standard
    defaults.set(codable: quotes, forKey: "quotes")
}

override func viewDidAppear(_ animated: Bool) {
    // Code to load the struct again after the view appears.
    let defaults = UserDefaults.standard
    quotes = defaults.codable(RandomItems.self, forKey: "quotes") ?? 
RandomItems([])
}

override func viewWillDisappear(_ animated: Bool) {
    // Code to save struct before the view disappears.
    let defaults = UserDefaults.standard
    if let quotes = quotes {
        defaults.set(codable: quotes, forKey: "quotes")
    }
}
}

extension UserDefaults {

func set<T: Encodable>(codable: T, forKey key: String) {
    let encoder = JSONEncoder()
    do {
        let data = try encoder.encode(codable)
        let jsonString = String(data: data, encoding: .utf8)!
        print("Saving \"\(key)\": \(jsonString)")
        self.set(jsonString, forKey: key)
    } catch {
        print("Saving \"\(key)\" failed: \(error)")
    }
}

func codable<T: Decodable>(_ codable: T.Type, forKey key: String) -> T? {
    guard let jsonString = self.string(forKey: key) else { return nil }
    guard let data = jsonString.data(using: .utf8) else { return nil }
    let decoder = JSONDecoder()
    print("Loading \"\(key)\": \(jsonString)")
    return try? decoder.decode(codable, from: data)
}
}

2 个答案:

答案 0 :(得分:0)

在ViewController中创建一个属性/变量,以保存RandomItems的值

var randomItems: RandomItems?

在viewWillDisappear方法中,使用您的密钥将数据保存到UserDefaults中。

if let propertyList = self.randomItems?.toPropertyList() {
   UserDefaults.standard.setValue(propertyList, forKey: "MyItems")
}

在viewWillAppear方法中,从UserDefaults获取数据并将其分配给您的变量

if let propertyList = UserDefaults.standard.dictionary(forKey: "MyItems") {
   self.randomItems = RandomItems(propertyList: propertyList)
} 

答案 1 :(得分:0)

设计此方法的一个好方法是使用一对辅助方法扩展 UserDefaults

extension UserDefaults {

    func set<T: Encodable>(codable: T, forKey key: String) {
        let encoder = JSONEncoder()
        do {
            let data = try encoder.encode(codable)
            let jsonString = String(data: data, encoding: .utf8)!
            print("Saving \"\(key)\": \(jsonString)")
            self.set(jsonString, forKey: key)
        } catch {
            print("Saving \"\(key)\" failed: \(error)")
        }
    }

    func codable<T: Decodable>(_ codable: T.Type, forKey key: String) -> T? {
        guard let jsonString = self.string(forKey: key) else { return nil }
        guard let data = jsonString.data(using: .utf8) else { return nil }
        let decoder = JSONDecoder()
        print("Loading \"\(key)\": \(jsonString)")
        return try? decoder.decode(codable, from: data)
    }
}

然后在QuotesViewController

中使用它
class QuotesViewController: UIViewController {

    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)
        }
    }

    var quotes: RandomItems! = RandomItems([
        "James",
        "John",
        "William",
    ])

    override func viewDidAppear(_ animated: Bool) {
        // Code to load the struct again after the view appears.
        let defaults = UserDefaults.standard
        quotes = defaults.codable(RandomItems.self, forKey: "quotes")
    }

    override func viewWillDisappear(_ animated: Bool) {
        // Code to save struct before the view disappears.
        let defaults = UserDefaults.standard
        if let quotes = quotes {
            defaults.set(codable: quotes, forKey: "quotes")
        }
    }
}

输入(并退出)上述视图控制器会打印:

  

保存&#34;报价&#34;:{&#34;项目&#34;:[&#34; James&#34;,&#34; John&#34;,&#34; William&#34; ]&#34;看出&#34;:0}
  正在加载&#34;报价&#34;:{&#34;项目&#34;:[&#34; James&#34;,&#34; John&#34;,&#34; William&#34;],& #34;看出&#34;:0}

<强>更新即可。对于它的价值,下面是我用来在Xcode 9游乐场测试的完整的代码:

import Foundation

extension UserDefaults {

    func set<T: Encodable>(codable: T, forKey key: String) {
        let encoder = JSONEncoder()
        do {
            let data = try encoder.encode(codable)
            let jsonString = String(data: data, encoding: .utf8)!
            print("Saving \"\(key)\": \(jsonString)")
            self.set(jsonString, forKey: key)
        } catch {
            print("Saving \"\(key)\" failed: \(error)")
        }
    }

    func codable<T: Decodable>(_ codable: T.Type, forKey key: String) -> T? {
        guard let jsonString = self.string(forKey: key) else { return nil }
        guard let data = jsonString.data(using: .utf8) else { return nil }
        let decoder = JSONDecoder()
        print("Loading \"\(key)\": \(jsonString)")
        return try? decoder.decode(codable, from: data)
    }
}

class UIViewController: NSObject {
    func viewDidAppear(_ animated: Bool) { }
    func viewWillDisappear(_ animated: Bool) { }
}

class QuotesViewController: UIViewController {

    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)
        }
    }

    var quotes: RandomItems! = RandomItems([
        "James",
        "John",
        "William",
        "Mary",
        "Sarah",
        "Michael",
        "Steve",
        "Lisa",
        "Jeff",
        "Chris",
        ])

    override func viewDidAppear(_ animated: Bool) {
        // Code to load the struct again after the view appears.
        let defaults = UserDefaults.standard
        quotes = defaults.codable(RandomItems.self, forKey: "quotes")
    }

    override func viewWillDisappear(_ animated: Bool) {
        // Code to save struct before the view disappears.
        let defaults = UserDefaults.standard
        if let quotes = quotes {
            defaults.set(codable: quotes, forKey: "quotes")
        }
    }
}

let vc = QuotesViewController()

vc.viewWillDisappear(false)
vc.quotes = nil

vc.viewDidAppear(true)
print(vc.quotes)