1

我是编程新手。我已经创建了一个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)
}
}
4

2 回答 2

2

一个很好的设计方法是使用一对辅助方法进行扩展: 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")
        }
    }
}

进入(和退出)上面的视图控制器打印:

保存 "quotes": {"items":["James","John","William"],"seen":0}
加载 "quotes": {"items":["James","John","威廉"],"见过":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)
于 2017-10-22T13:22:14.270 回答
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)
} 
于 2017-10-22T11:49:53.213 回答