2017-12-09 22 views
0

配列から異なる文字列をランダムに表示するアプリケーションを作成しました。配列が繰り返されないようにするために、すでに表示されていないStringsのみを表示する構造体を作成しました。構造体の順序を保存する方法は?

これはかなりうまくいきますが、私の問題は、シーンを切り替えるとすぐに構造体がリセットされ、ユーザーのデフォルトに保存しようとしたことです。 UserDefaultsを適用しようとしたときに私が間違っていた箇所を誰かが知っていますか?すでにUserDefaultsに格納された値を持っている場合は、あなたのviewDidLoadで確認することができ、あなたがviewDidAppearでコードを削除することができ

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

あなたはあなたがviewWillDisappearに保存されている値をリセットしているので、あなたはユーザデフォルトに引用符の新しい値を保存しているビューをロードするたびに。 –

+0

viewDidLoad()メソッドを変更する必要がありますか? @Francesco Deliro –

+0

私は答えを掲示して、それが助けてくれることを願っています。 –

答えて

0

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

は私の構造体は、保存方法を含むされます

EDIT:

そして、あなたは、あなたのアプリがバックグラウンドに移動したときにあなたの引用符を保存する場合:

は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() 
} 
+0

次のようにstructメソッドでエラーが発生します。let item = items.remove(at:index) - >致命的なエラー:インデックスが範囲外にある –

+0

ビューをロードすると、引用符varにはすでに値がありますか? trueの場合は、空のデフォルト値に引用符を設定したelseを削除します。私は私の答えを編集します。 –

+0

ありがとうございますが、動作しないのはアプリケーションを閉じるときだけです。その後、構造体は保存されません。 @Francesco Deliro –

関連する問題