Создайте экземпляр UIViewController с помощью init (из декодера: декодер)

Мне нужно сохранить ViewControllers, созданные пользователем, в файл json, и мне нужно позже воссоздать их либо на том же устройстве, либо на другом устройстве.

ViewControllers доступны в раскадровке, но я не могу правильно создать их экземпляр в функции инициализации (от декодера: декодера).

Это ViewController, который нужно сохранить и восстановить.

class SecondViewController: UIViewController, Encodable, Decodable {
@IBOutlet weak var textField: UITextField!

   private var restoreText: String?

   enum CodingKeys: CodingKey {
      case textField
   }

   func encode(to encoder: Encoder) throws {
      var container = encoder.container(keyedBy: CodingKeys.self)
      try container.encode(textField.text, forKey: .textField)
   }

   required init(from decoder: Decoder) throws {
       let container = try decoder.container(keyedBy: CodingKeys.self)
       restoreText = try? container.decode(String.self, forKey: .textField)
       super.init(nibName: "", bundle: nil)
   }

   required init?(coder: NSCoder) {
       super.init(coder: coder)
   }

   override func viewDidLoad() {
       super.viewDidLoad()
       if let text = restoreText {
          textField.text = text
       }
   }

   @IBAction func save(_ sender: Any) {
      do {
        let jsonData = try JSONEncoder().encode(self)
        let s = String(data: jsonData, encoding: .ascii)
        print("Widgets \(s!)")

        let filename = getDocumentsDirectory().appendingPathComponent("output.txt")
        try jsonData.write(to: filename)
      } catch {
        print(error.localizedDescription)
      }
  }
}

Здесь я загружаю контроллер из файла json и пытаюсь его воссоздать.

...

do {
      let filename = getDocumentsDirectory().appendingPathComponent("output.txt")
      let jsonData = try Data(contentsOf: filename)
      if let s = String(data: jsonData, encoding: .ascii) {
         let controller = try JSONDecoder().decode(SecondViewController.self, from: jsonData)
         let frame = CGRect(x: 0, y: 0, width: view.frame.width * 0.8, height: view.frame.height * 0.8)
         controller.view.frame = frame
         controller.view.center = view.center
         view.addSubview(controller.view)
         addChild(controller)
      }
    } catch {
        print(error.localizedDescription)
    }
...

Запустив этот код, я получаю следующую ошибку:

*** Assertion failure in -[UINib initWithNibName:directory:bundle:], /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3920.26.113/UINib.m:97
2020-04-18 09:44:03.543891+0200 ViewControllerSerialization[7764:504964] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: (name != nil) && ([name length] > 0)'

Насколько я понимаю, эта ошибка связана с тем, что контроллер не был загружен из раскадровки.

Вопрос в том, как правильно инициализировать ViewController из раскадровки в функции инициализации (из декодера: декодера)?


person Fab    schedule 18.04.2020    source источник
comment
stackoverflow.com/questions/30449137/ stackoverflow.com/questions /24035984/ и т.д.   -  person Larme    schedule 18.04.2020
comment
Но это странно. для хранения ViewControllers, созданных пользователем, в json: вместо этого я бы пошел по этому пути: мне нужно сохранить CustomViewModel в JSON и иметь возможность инициировать ViewController с этой настраиваемой моделью.   -  person Larme    schedule 18.04.2020
comment
у вас есть ошибка, потому что вы кодируете текстовое поле формы String.self и пытаетесь декодировать его в SecondViewController.self, типы не совпадают   -  person Dialogue    schedule 18.04.2020