2017-02-22 1 views
0

Редактировать: Я заметил, что я использую разные ключи (играл с кодом), но даже если они такие же, я получаю похожие результаты.UserDefaults не сохраняются в TextView

Я просмотрел StackOverflow, но не нашел решение для этого. У меня есть текстовое представление на втором представлении в моей раскадровке, и мне нужно, чтобы он сохранял данные без нажатия кнопки. Я должен перейти к представлению, увидеть текст и когда фоны приложения (или вид исчезнут), он должен сохранять эти данные.

У меня есть работа с точкой, когда текст появляется на втором представлении (через segue), но он не обновляется новым текстом, который добавляется через цикл и не сохраняет данные. Кроме того, если я нажимаю кнопку «Очистить», чтобы очистить представление, он очищает текст, но как только я вернусь к просмотру, данные вернутся.

По сути, он застрял в сохранении только одной строки моего текста и ничего больше. Любая помощь будет назначена, поскольку я очень новичок в Xcode. (Последний Xcode с Swift 3).

import Foundation 
import UIKit 

class CalcViewController: UIViewController { 
    var tape = Array<String>() 

    @IBOutlet weak var calcTape: UITextView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     for eachNewLineInTape in tape { 
      calcTape.text = calcTape.text + eachNewLineInTape + "\r\n" 
     } 

     let sel:Selector = #selector(self.appMovedToBackground) 
     let notificationCentre = NotificationCenter.default 
     notificationCentre.addObserver(self, selector: sel, name: NSNotification.Name.UIApplicationWillResignActive, object: nil) 

     let defaults = UserDefaults.standard 

     if let userDataNew:AnyObject = defaults.object(forKey: "userDataNew") as AnyObject?{ 
      calcTape.text = (userDataNew as! Array).first 

      print("SAVED") 
     } 
     else { 
      print("not saved") 
     } 
    } 

    @IBAction func clearAll(_ sender: UIButton) { 
     // if the tape is not empty... 
     if (calcTape.text != ""){ 
      // empty it (set to empty string) 
      calcTape.text = "" 
      let bundleIdentifier = Bundle.main.bundleIdentifier 
      UserDefaults.standard.removePersistentDomain(forName: bundleIdentifier!) 
     } else { 
      // otherwise, it was already empty, so display a message 
      let alert = UIAlertController(title: "Alert", message: "Nothing to clear", preferredStyle: UIAlertControllerStyle.alert) 
      alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) 
      self.present(alert, animated: true, completion: nil) 
     } 
    } 

    func appMovedToBackground(){ 
     print("App moved to background") 
     let myText = calcTape.text 
     UserDefaults.standard.set(myText, forKey: "savedStringKey") 
     UserDefaults.standard.synchronize() 
     print("saved") 
    } 
} 
+0

Это помогло бы много, если вы использовали один и тот же ключ для сохранение и загрузка данных в/из пользовательских значений по умолчанию. Еще лучше объявить константу и использовать ее в обоих местах. – rmaddy

+0

Вы используете два разных ключа; 'userDataNew' и' savedStringKey'. Один из них сохраняет массив, а другой имеет строку. И пользовательские значения по умолчанию не предназначены для хранения данных. Да, узнайте, как использовать пользовательские настройки по умолчанию. Нет, не узнайте, как использовать его в качестве хранилища данных. Используйте plists или Core Data или Realm или ... – Paulw11

+0

@rmaddy, даже если они такие же, я получаю аналогичные результаты. –

ответ

0

Я предполагаю, что Вы проверили и убедились, что appMovedToBackground называется.

Во-первых, как уже упоминалось в комментариях, вам нужно использовать тот же ключ.

Затем в коде экономии:

let myText = calcTape.text 
UserDefaults.standard.set(myText, forKey: "savedStringKey") 

myText имеет String тип, поэтому он должен хранить его как есть.

Но тогда в вашем коде загрузки вы делаете что-то действительно странное. Эта строка должна быть успешной, и у userDataNew будет сохраненная строка.

if let userDataNew:AnyObject = defaults.object(forKey: "userDataNew") as AnyObject?{ 

Но после того, что вы сила приведения его в Array. Ваша программа должна врезаться сразу:

calcTape.text = (userDataNew as! Array).first 

Правильный путь для загрузки должно быть только:

calcTape.text = UserDefaults.standard.string(forKey: "savedStringKey") 

Немного не по теме, но несколько улучшений в коде: Вместо этого:

for eachNewLineInTape in tape { 
    calcTape.text = calcTape.text + eachNewLineInTape + "\r\n" 
} 

вы могли бы написать:

calcTape.text = tape.joined(separator: "\r\n") 
+0

Работает нормально, и это заставило меня изменить «если разрешить userDataNew: AnyObject ....» на «if let _: AnyObject = defaults ....». Когда я вернусь к своему первому представлению, чтобы добавить больше данных/текста в это текстовое представление, он не добавляется - он запоминает только первую запись. И когда я выхожу из приложения из многозадачности, он не восстанавливает данные должным образом. Любой совет здесь? –

+0

Также изменил все ключи на «savedStringKey» –

+0

Если вы убьете свое приложение, уведомление определенно не будет вызвано. Возможно, зная конкретный вариант использования, было бы лучше найти определенные события для обнаружения, когда вход должен быть сохранен. Что касается загрузки, вы можете переместить свой код загрузки в 'viewWillAppear', если вы вернетесь к нему, вместо того, чтобы повторно установить VC. – Dmitry

0

К сожалению для ответа на свой вопрос (не знаю, как еще это сделать, и сделать это ясно), но это, как код выглядит сейчас:

import Foundation 
import UIKit 

class ViewControllerTwo: UIViewController { 

var tape = Array<String>() 

@IBOutlet weak var calcTape: UITextView! 



override func viewDidLoad() { 
    super.viewDidLoad() 

    calcTape.text = tape.joined(separator: "\r\n") 

    let sel:Selector = #selector(self.appMovedToBackground) 
    let notificationCentre = NotificationCenter.default 
    notificationCentre.addObserver(self, selector: sel, name: NSNotification.Name.UIApplicationWillResignActive, object: nil) 

    let defaults = UserDefaults.standard 

    if let _:AnyObject = defaults.object(forKey: "savedStringKey") as AnyObject?{ 

     calcTape.text = UserDefaults.standard.string(forKey: "savedStringKey") 

     print("SAVED") 
    } 
    else { 
     print("not saved") 
    } 


} 

@IBAction func clearAll(_ sender: UIButton) { 

    // if the tape is not empty... 
    if (calcTape.text != ""){ 

     // empty it (set to empty string) 

     calcTape.text = "" 
     let bundleIdentifier = Bundle.main.bundleIdentifier 
     UserDefaults.standard.removePersistentDomain(forName: bundleIdentifier!) 


    } else { 
     // otherwise, it was already empty, so display a message 
     let alert = UIAlertController(title: "Alert", message: "Nothing to clear", preferredStyle: UIAlertControllerStyle.alert) 
     alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) 
     self.present(alert, animated: true, completion: nil) 
    } 
} 


func appMovedToBackground(){ 
    print("App moved to background") 
    let myText = calcTape.text 
    UserDefaults.standard.set(myText, forKey: "savedStringKey") 
    print("saved in bg") 
    } 
} 
+0

вы можете редактировать свой оригинальный вопрос – Dmitry

Смежные вопросы