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

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

最佳答案

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

进入(和退出)上述 View Controller 会打印:

Saving "quotes": {"items":["James","John","William"],"seen":0}
Loading "quotes": {"items":["James","John","William"],"seen":0}


更新。就其值(value)而言,下面是我用来在 Xcode 9 Playground 中测试此代码的完整代码:

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)

关于swift - 我如何使用 UserDefaults 来保存和加载我的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46873214/

相关文章:

c - 结构输出显示错误

C++ 结构和类编译器错误

php - 将 PHP 生成的网页下载为 HTML 文件

ios - 如何使用 NSUserDefaults Swift 存储自定义对象数组

ios - 当键盘出现 Swift 时出现移动 View 问题

ios - 如何在 Swift 框架中导入私有(private)框架头文件?

ios - 如何在 Xcode 中正确设置 GCController valueChangeHandler?

C# 将大型结构编码到 C DLL

c++ - 使用 FMOD 将输出保存到磁盘

android 为位图命名并保存