2017-01-07 6 views
1

스위프트 놀이터를 사용하여 NSCoding을 사용하여 부모 - 자식 관계를 작성하고 있습니다.스위프트 NSCoding - 인코딩 된 배열을 읽는 방법

의 관계는 설명 될 수있다 : 나는이 책의 컬렉션을 저장하려고하면

One Author can write many 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.

내 스위프트 놀이터 코드는 다음과 같습니다.

// 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") 
} 

내 질문 사항 : 무엇이 오류의 원인이며 어떻게 문제를 해결할 수 있습니까?

많은 감사합니다.

답변

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)") 
    } 
} 

이것은 작동하는 것 같습니다.

문제 종료