斯威夫特NSCoding - 如何读出的编码阵列(Swift NSCoding - How to

2019-09-29 19:48发布

我使用的是斯威夫特游乐场编写使用NSCoding父子关系。

的关系可以描述为:

一个Author可以写很多Books

但是,它会导致当我尝试保存藏书的错误;

游乐场执行中止:错误:执行被中断,原因:EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子码=为0x0)。 该工艺已在留下它被中断的点,用“线程返回-x”表达评价前返回的状态。

我斯威夫特游乐场代码如下;

// Author model
class Author: NSObject, NSCoding
{
    var name: String
    var books:[Book] = [Book]()

    init(name:String, books:[Book]?) {
        self.name = name
        guard let bookList = books else {
            return
        }
        self.books = bookList
    }

    required convenience init?(coder aDecoder: NSCoder) {
        let name = aDecoder.decodeObject(forKey:"name") as! String
        let books = aDecoder.decodeObject(forKey:"books") as! [Book]

        self.init(name:name, books:books)
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey:"name")
        aCoder.encode(books, forKey:"books")
    }

}

// Book model
class Book: NSObject, NSCoding {
    var title: String
    var author: Author?

    init(title:String, author: Author?) {
        self.title = title
        self.author = author
    }

    public convenience required init?(coder aDecoder: NSCoder) {

        let title = aDecoder.decodeObject(forKey: "title") as! String
        let author = aDecoder.decodeObject(forKey: "author") as! Author

        self.init(title:title, author:author)
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(title, forKey: "title")
        aCoder.encode(author, forKey: "author")
    }
}

// Create the data
var author:Author = Author(name: "Tom Clancy", books: nil)
let book0 = Book(title: "The Hunt for Red October", author: author)
let book1 = Book(title: "Red Storm Rising", author: author)
author.books.append(contentsOf: [book0, book1])

// -----------
// Save data

let manager = FileManager.default
let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first! as URL
let writePath: URL = url.appendingPathComponent("archive.plist")

print("Attempting to save to: \(writePath)")

let saveData = NSMutableData()

let archiver = NSKeyedArchiver(forWritingWith: saveData)
archiver.encode(books, forKey:"books")
archiver.encode(author, forKey: "author")
//NSKeyedArchiver.archiveRootObject(books, toFile: writePath.path)
archiver.finishEncoding()

_ = saveData.write(to: writePath, atomically: true)


// -----------
// Load data

print("Attempting to load from: \(writePath)")

if FileManager.default.fileExists(atPath: writePath.path) {
    if let saveData = try? Data(contentsOf: writePath) {
        let unarchiver = NSKeyedUnarchiver(forReadingWith: saveData)

// Crash occurs here
            var authorData = unarchiver.decodeObject(forKey: "author") as! Author
print (authorData.name)


    }
} else {
    print("No data archive exists")
}

所以我的问题是:是什么原因造成的错误,我怎么能纠正这个问题?

非常感谢

Answer 1:

我能够通过重构我的代码来解决这个问题。

class Author: NSObject, NSCoding
{
    var name: String
    var books:[Book] = [Book]()

    init(name:String, books:[Book]?) {
        self.name = name
        guard let bookList = books else {
            return
        }
        self.books = bookList
    }

    required convenience init?(coder aDecoder: NSCoder) {
        let name = aDecoder.decodeObject(forKey:"name") as! String
        let books = aDecoder.decodeObject(forKey:"books") as! [Book]

        self.init(name:name, books:books)
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey:"name")
        aCoder.encode(books, forKey:"books")
    }

}

class Book: NSObject, NSCoding {
    var title: String
    var author: Author

    init(title:String, author: Author) {
        self.title = title
        self.author = author
    }

    public convenience required init?(coder aDecoder: NSCoder) {

        let title = aDecoder.decodeObject(forKey: "title") as! String
        let author = aDecoder.decodeObject(forKey: "author") as! Author

        self.init(title:title, author:author)
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(title, forKey: "title")
        aCoder.encode(author, forKey: "author")
    }
}

let author:Author = Author(name: "Tom Clancy", books: nil)
let books = [
    Book(title: "The Hunt for Red October", author: author)
    , Book(title: "Red Storm Rising", author: author)
]
//author.books.append(contentsOf: books)


// -----------
// Save data


let manager = FileManager.default
let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first! as URL
let writeFile: URL = url.appendingPathComponent("books.data")

print ("Attempting to write to: \(writeFile.path)")

NSKeyedArchiver.archiveRootObject(books, toFile: writeFile.path)

if let bookData = NSKeyedUnarchiver.unarchiveObject(withFile: writeFile.path) as? [Book] {
    for book in bookData {
        print ("\(book.title) - \(book.author.name)")
    }
}

这似乎工作。

问题关闭



文章来源: Swift NSCoding - How to read an encoded array