I'm using Swift playground to write a parent-child relationship using NSCoding.
The relationship can be described as:
One
Authorcan write manyBooks
However, it causes an error when I try to save the collection of books;
Playground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0). The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
My Swift playground code is as follows;
// 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")
}
So my question is: What is causing the error and how can I rectify the issue?
Many thanks
                        
I was able to solve this problem by refactoring my code.
This seems to work.
Issue closed