【问题标题】:How do I save data using NSKeyedArchiver?如何使用 NSKeyedArchiver 保存数据?
【发布时间】:2017-09-26 02:33:26
【问题描述】:

我非常接近使用 Swift 4 和 iOS 11 完成我的第一个 iOS 应用程序。

该应用程序有一个显示在表格视图控制器中的列表和一个带有可编辑 UITextView 对象的详细视图。我的目标是让用户能够对 UITextView 中的内容进行编辑并使用 NSKeyedArchiver 保存这些更改。

我已完成列表视图并连接了详细视图。您可以进行编辑,但不会保存。

我已确认该条目确实保存到会话后仍然存在的内存中,但编辑没有保存。

文档审查和学习多个教程并未提供所需的见解。我附上了一个屏幕截图来显示详细视图的界面,这里是详细视图控制器的代码,其中保存按钮触发了保存操作:

import UIKit
import os.log

class ViewController: UIViewController, UINavigationControllerDelegate, UITextViewDelegate  {

  var season: Season?

  //MARK: Properties

  @IBOutlet weak var seasonDetail: UITextView!
  @IBAction func saveButton(_ sender: UIBarButtonItem) {
    if let selectedDetail = seasonDetail.text {
      seasonDetail.text = selectedDetail
    } else {
      print("failed to save changes.")
    }
    saveChanges()
    print("Save button clicked")
  }

  override func viewDidLoad() {
    super.viewDidLoad()

      title = season?.name
      seasonDetail.text = season?.detail
    seasonDetail.delegate=self
  }

  override func viewWillDisappear(_ animated: Bool) {
    season?.detail = (seasonDetail?.text)!
  }

  func textViewDidEndEditing(_ textView: UITextView) {
    seasonDetail.text = season?.detail
  }

  //MARK: UITextViewdDelegate

  func textViewShouldReturn(_ textView: UITextView) -> Bool {
    textView.resignFirstResponder()

    return true
  }


 func saveChanges() {
    print("Saving items to: \(Season.ArchiveURL)")
    let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(season as Any, toFile: Season.ArchiveURL.path)

    if isSuccessfulSave {
      os_log("Season sucessfully saved.", log: OSLog.default, type: .debug)
    } else {
      os_log("Failed to save season.", log: OSLog.default, type: .debug)
    }
  }

}

这是数据模型类的代码:

import UIKit
import os.log

class Season: NSObject, NSCoding {

  //MARK: Properties

  var name: String
  var detail: String

  //MARK: Archiving Paths

  static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
  static let ArchiveURL = DocumentsDirectory.appendingPathComponent("season")

  //MARK: Types

  struct PropertyKey {
    static let name = "name"
    static let detail = "detail"
  }


  //MARK: Initialization
  init?(name: String, detail: String) {

    guard !name.isEmpty else {
      return nil
    }

    guard !detail.isEmpty else {
      return nil
    }

    // Initialize stored properties
    self.name = name
    self.detail = detail

  }

  //MARK: NSCoding

  func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: PropertyKey.name)
    aCoder.encode(detail, forKey: PropertyKey.detail)
  }

  required convenience init?(coder aDecoder: NSCoder) {

    // the name is required. If we cannnot get a name string, the initializer should fail.
    guard let name = aDecoder.decodeObject(forKey: PropertyKey.name) as? String
      else {
      os_log("Unable to decode the name for a Season object.", log: OSLog.default, type: .debug)
      return nil
    }

    let detail = aDecoder.decodeObject(forKey: PropertyKey.detail)

    self.init(name: name, detail: detail as! String)
    }
  }

我的目标是了解我的代码中缺少什么,并知道如何保存所有数据,包括编辑。我将不胜感激任何有帮助的方向。

【问题讨论】:

    标签: uitextview ios11 nscoding swift4 nskeyedarchiver


    【解决方案1】:

    请检查:

    class ViewController: UIViewController, UINavigationControllerDelegate, UITextViewDelegate  {
        var season: Season?
        @IBOutlet weak var seasonDetail: UITextView!
        @IBAction func saveButton(_ sender: UIBarButtonItem) {
            if let selectedDetail = seasonDetail.text {
                season?.detail = selectedDetail // this is the line
            } else {
                print("failed to save changes.")
            }
            saveChanges()
            print("Save button clicked")
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            if season == nil {
                season = Season(name: "Season Name", detail: "Season Details")
            }
            title = season?.name
            seasonDetail.text = season?.detail
            seasonDetail.delegate=self
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            season?.detail = (seasonDetail?.text)!
        }
    
        func textViewDidEndEditing(_ textView: UITextView) {
             season?.detail = seasonDetail.text
        }
    
        //MARK: UITextViewdDelegate
        func textViewShouldReturn(_ textView: UITextView) -> Bool {
            textView.resignFirstResponder()
            return true
        }
    
        func saveChanges() {
            print("Saving items to: \(Season.ArchiveURL)")
            let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(season as Any, toFile: Season.ArchiveURL.path)
    
            if isSuccessfulSave {
                os_log("Season sucessfully saved.", log: OSLog.default, type: .debug)
            } else {
                os_log("Failed to save season.", log: OSLog.default, type: .debug)
            }
        }
    }
    

    【讨论】:

    • 您好 Vini,如何指示更新后的值?谢谢。
    • 我通过使用seasonDetail.text更新详细信息来做到这一点
    • 不,它不会保存它。我能提供什么进一步的帮助来解决这个问题吗?
    • 更新了答案。请检查
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多