【问题标题】:NSCoding decodeObject always nilNSCoding decodeObject 总是 nil
【发布时间】:2019-12-22 05:34:31
【问题描述】:

我是swift的新手,请帮忙。 尝试归档和取消归档对象并在磁盘上写入/读取。

我有一个类 FourLines

class FourLines: NSObject, NSCoding, NSSecureCoding, NSCopying {

    static var supportsSecureCoding: Bool{
        return true
    }


    private static let linesKey = "linesKey"
    var lines: [String]?

    override init() {
    }

    required init?(coder aDecoder: NSCoder) {
        print("FourLines init")
        lines = aDecoder.decodeObject(forKey: FourLines.linesKey) as? [String]
    }

    func encode(with aCoder: NSCoder) {
        print("FourLines encode")
        if let saveLines = lines {
            aCoder.encode(saveLines, forKey: FourLines.linesKey)
        }
    }

    func copy(with zone: NSZone? = nil) -> Any {
        print("copy with zone")
        let copy = FourLines()
        if let linesToCopy = lines {
            var newLines = Array<String>()
            for line in linesToCopy {
                newLines.append(line)
            }
            copy.lines = newLines
        }
        return copy
    }


}

在 ViewController 中我尝试保存和读取数据:

class ViewController: UIViewController {

    private static let linesKey = "linesKey"

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let fileURL = self.dataFileUrl()
        if FileManager.default.fileExists(atPath: fileURL.path!) {

            let codedData = try! Data(contentsOf: fileURL as URL)
            print(codedData)
            let unarchiver = try! NSKeyedUnarchiver(forReadingFrom: codedData)
            if unarchiver.containsValue(forKey: ViewController.linesKey) {
                print("viewDidLoad contains value")
            } else {
                print("viewDidLoad doesn't conains value")
            }

            let fourLines = unarchiver.decodeObject(forKey: ViewController.linesKey) as! FourLines?
            print(fourLines?.lines?.count)

        }
        let app = UIApplication.shared
        NotificationCenter.default.addObserver(self, selector: #selector(self.applicationWillResignActive(notification:)), name: UIApplication.willResignActiveNotification, object: app)
    }

    @objc func applicationWillResignActive(notification: NSNotification) {
        print("applicationWillResignActive")
        let fileURL = self.dataFileUrl()
        print(fileURL)
        let fourLines = FourLines()
        let array = (self.lineFields as NSArray).value(forKey: "text") as! [String]
        fourLines.lines = array
        let archiver = NSKeyedArchiver(requiringSecureCoding: true)
        archiver.encode(fourLines, forKey: ViewController.linesKey)
        let data = archiver.encodedData
        do {
            try data.write(to: fileURL as URL)
        } catch {
            print("Error is \(error)")
        }

    }

    @IBOutlet var lineFields: [UITextField]!

    func dataFileUrl() -> NSURL {
        let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        var url: NSURL?
        url = URL(fileURLWithPath: "") as NSURL
        do {
            try url = urls.first!.appendingPathComponent("data.archive") as NSURL
        } catch {
            print("Error is \(error)")
        }
        return url!
    }
}

当我辞职时应用编码方法调用: 四行编码

当我尝试加载它时,我看到文件已创建并且它包含值,但是在解码fourLines 对象时我总是有 nil:

322 字节 viewDidLoad 包含值 无

然后初始化? coder aDecoder 和带有区域的复制从不调用。 我哪里错了?

【问题讨论】:

  • 不要使用NSCoding,使用CodableJSONEncoder/PropertyListEncoder

标签: ios swift


【解决方案1】:

你的问题是你从来没有初始化你的行数组。将其声明更改为非可选并使用空数组对其进行初始化。试试这样:

class FourLines: NSObject, NSCoding, NSSecureCoding, NSCopying {

    static var supportsSecureCoding: Bool { return true }

    private static let linesKey = "linesKey"

    var lines: [String] = []

    override init() { }

    required init?(coder aDecoder: NSCoder) {
        print(#function)
        lines = aDecoder.decodeObject(forKey: FourLines.linesKey) as? [String] ?? []
    }

    func encode(with aCoder: NSCoder) {
        print(#function)        
        aCoder.encode(lines, forKey: FourLines.linesKey)
    }
    func copy(with zone: NSZone? = nil) -> Any {
        print(#function)
        let copy = FourLines()
        var newLines = Array<String>()
        for line in lines {
            newLines.append(line)
        }
        copy.lines = newLines
        return copy
    }
}

游乐场测试:

let fourLines = FourLines()
fourLines.lines = ["line1","line2","line3","line4"]

let data = try! NSKeyedArchiver.archivedData(withRootObject: fourLines, requiringSecureCoding: true)

let decodedFourlInes = try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as! FourLines
decodedFourlInes.lines  // ["line1", "line2", "line3", "line4"]

顺便说一句,如果您尝试保留文本字段值,您的 ViewController 应该如下所示:

class ViewController: UIViewController {
    @IBOutlet var lineFields: [UITextField]!
    private static let dataFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("lines.plist")
    override func viewDidLoad() {
        super.viewDidLoad()
        do {
            let lines = (try NSKeyedUnarchiver
                .unarchiveTopLevelObjectWithData(Data(contentsOf: ViewController.dataFileUrl)) as! FourLines)
                .lines
            var index = 0
            lineFields.forEach {
                $0.addTarget(self, action: #selector(editingDidEnd), for: .editingDidEnd)
                $0.text = lines[index]
                index += 1
            }
        } catch {
            print(error)
        }
    }
    @objc func editingDidEnd(_ textField: UITextField) {
        print(#function)
        let fourLines = FourLines()
        fourLines.lines = lineFields.map { $0.text! }
        do {
            try NSKeyedArchiver
                .archivedData(withRootObject: fourLines, requiringSecureCoding: true)
                .write(to: ViewController.dataFileUrl)
        } catch {
            print(error)
        }
    }
}

【讨论】:

    猜你喜欢
    • 2017-02-08
    • 2012-05-29
    • 2020-05-29
    • 2017-03-28
    • 2015-03-05
    • 2014-08-25
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多