【问题标题】:How to save the order of a struct?如何保存结构的顺序?
【发布时间】:2017-12-09 11:09:45
【问题描述】:

我创建了一个应用程序,它随机显示数组中的不同字符串。为了确保没有数组重复,我创建了一个结构,它只显示尚未显示的字符串。

效果很好,但我的问题是,一旦我切换场景,结构就会重置,尽管我试图将其保存为用户默认值。 当我尝试应用 UserDefaults 时,有人知道我在哪里犯了错误吗?

这是我的包含保存方法的结构:

 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
    if let quotes = defaults.codable(RandomItems.self, forKey: "quotes") as? RandomItems {
        self.quotes = quotes
    }
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector:Selector(("saveData:")), name: Notification.Name.UIApplicationWillTerminate, object:nil)
}
func storeQuotes() {
    // Code to save struct
    let defaults = UserDefaults.standard
    if let quotes = quotes {
        defaults.set(codable: quotes, forKey: "quotes")
    }
}
override func viewDidAppear(_ animated: Bool) {
    // Code to load the struct again after the view appears.

}

override func viewWillDisappear(_ animated: Bool) {

     storeQuotes()
}
func saveData(notification: Notification) {
    // Save your data here when app is closed
    print("Saving data...")
    storeQuotes()
  }

 }

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

【问题讨论】:

  • 每次加载视图时,您都会在用户默认值中保存一个新的引号值,因此您正在重置存储在 viewWillDisappear 中的值。
  • 我是否必须更改 viewDidLoad() 方法? @Francesco Deliro
  • 我已经发布了一个答案,希望对您有所帮助。

标签: ios swift struct save nsuserdefaults


【解决方案1】:

如果您已经在 UserDefaults 中存储了一个值,您可以检查您的 viewDidLoad,并且您可以在 viewDidAppear 中删除您的代码:

override func viewDidLoad() {
    let defaults = UserDefaults.standard
    if let quotes = defaults.codable(RandomItems.self, forKey: "quotes") as? RandomItems { 
        self.quotes = quotes 
    } 
}

编辑:

如果您想在应用移至后台时存储您的报价:

在 viewWillAppear 中添加通知观察者:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(saveData), name: Notification.Name.UIApplicationDidEnterBackground, object:nil)
}

func storeQuotes() {
    // Code to save struct 
    let defaults = UserDefaults.standard
    if let quotes = quotes {
        defaults.set(codable: quotes, forKey: "quotes")
    }
}

override func viewWillDisappear(_ animated: Bool) {
    // Code to save struct before the view disappears.
    storeQuotes()
}

func saveData() {
    // Save your data here when app is closed 
    print("Saving data...")
    storeQuotes()
}

【讨论】:

  • 我在struct方法的这一行得到一个错误:let item = items.remove(at:index) --> 致命错误:索引超出范围
  • 当您加载视图时,您的报价变量已经有了值?如果为 true,则删除我将引号设置为空默认值的 else。我将编辑我的答案。
  • 感谢它现在可以工作,但唯一不工作的是当我关闭应用程序时。然后结构不会被保存。 @Francesco Deliro
  • 不客气,您可以为 applicationWillTerminate 注册一个通知并将您的值保存在相应的操作中,检查此堆栈溢出答案:https://stackoverflow.com/questions/27010431/call-function-on-app-termination-in-swift
  • 我必须在 saveData() 函数中填写什么?我更新了我的代码@Francesco Deliro
猜你喜欢
  • 2016-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多