简体   繁体   中英

How to save the order of a struct?

I created an app which randomly displays different Strings from an array. To make sure that no array gets repeated I created a struct which only shows the Strings which haven´t already been displayed.

That works pretty well, but my problem is that as soon as I switch scenes the struct gets reset although I tried to save it to user defaults. Does someone know where I made a mistake when I tried to apply UserDefaults?

Here is my struct containing the saving methods:

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

You can check in your viewDidLoad if you already have a value stored in UserDefaults, and you can remove your code in viewDidAppear:

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

EDIT:

And if you want to store your quotes when your app moves to background:

Add the notification observer in 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()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM