无法找出编码器aDecoder:NSCoder

时间:2015-06-22 20:12:07

标签: ios xcode swift

我正在制作一个用于存档图书的应用程序,我正在连接按钮以保存数据,但我无法通过初始化。

以下是Xcode给我的错误:

Property 'self.bookStore' not initialised at super.init call.

这是我的代码:

import UIKit

class AddBook: UIViewController {

    @IBOutlet weak var bookAuthor: UITextField!
    @IBOutlet weak var bookTitle: UITextField!

    let bookStore: BookStore

    init(bookStore: BookStore) {
        self.bookStore = bookStore
        super.init(nibName: nil, bundle: nil)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder) // Error: Property 'self.bookStore' not initialised at super.init call.
    }


    @IBAction func saveNewBook(sender: AnyObject) {
        let author = self.bookAuthor.text!
        let title = self.bookTitle.text!

        bookStore.addBook(author, title: title)
        println("\(bookStore)")
    }
}


import UIKit

class BookStore: NSObject {

    var allBooks: [Book] = []

    func addBook(author: String, title: String) -> Book {
        let newBook = Book(author: author, title: title)

        allBooks.append(newBook)

        return newBook
    }
}

3 个答案:

答案 0 :(得分:2)

您的自定义初始值设定项无法初始化immutable属性。如果您希望它是不可变的,那么只需在其中一个必需或指定的初始化程序中初始化,而不是创建自定义初始化程序。

像这样,

class AddBook: UIViewController {

    @IBOutlet weak var bookAuthor: UITextField!
    @IBOutlet weak var bookTitle: UITextField!

    let bookStore: BookStore

    required init(coder aDecoder: NSCoder) {
        fatalError("Cannot be instantiated from storyboard")
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        bookStore = BookStore()
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }


    @IBAction func saveNewBook(sender: AnyObject) {
        let author = self.bookAuthor.text!
        let title = self.bookTitle.text!

        bookStore.addBook(author, title: title)
    }
}

或者这个,

class AddBook: UIViewController {

    @IBOutlet weak var bookAuthor: UITextField!
    @IBOutlet weak var bookTitle: UITextField!

    let bookStore: BookStore

    required init(coder aDecoder: NSCoder) {
        bookStore = BookStore()
        super.init(coder: aDecoder)
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        fatalError("Cannot be instantiated from code")

    }


    @IBAction func saveNewBook(sender: AnyObject) {
        let author = self.bookAuthor.text!
        let title = self.bookTitle.text!

        bookStore.addBook(author, title: title)
    }
}

但是,在你的情况下,你希望它是不可变的,因为你正在使用让bookStore:BookStore ,但如果你没有使用故事板,你可以简单地从所需的初始化程序中抛出致命的异常并使用你的像这样拥有初始化程序,

class AddBook: UIViewController {

    @IBOutlet weak var bookAuthor: UITextField!
    @IBOutlet weak var bookTitle: UITextField!

    let bookStore: BookStore

    init(bookStore: BookStore) {
        self.bookStore = bookStore
        super.init(nibName: nil, bundle: nil)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("cannot be initialized from storyboard")
    }

    @IBAction func saveNewBook(sender: AnyObject) {
        let author = self.bookAuthor.text!
        let title = self.bookTitle.text!

        bookStore.addBook(author, title: title)
    }
}


let book = AddBook(bookStore: BookStore())

现在,您需要拥有所需的初始化程序,您必须使该属性可变,以便您可以从这样的自定义初始化程序设置它,

class AddBook: UIViewController {

    @IBOutlet weak var bookAuthor: UITextField!
    @IBOutlet weak var bookTitle: UITextField!

    var bookStore: BookStore!

    init(bookStore: BookStore) {
        self.bookStore = bookStore
        super.init(nibName: nil, bundle: nil)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    @IBAction func saveNewBook(sender: AnyObject) {
        let author = self.bookAuthor.text!
        let title = self.bookTitle.text!

        bookStore.addBook(author, title: title)
    }
}


let book = ... // initialized from storyboard or using performSegueWithIdentifier:

book.bookStore =  BookStore()

这里的主要哲学是,没有两个初始化器可以初始化不可变属性。只有一个可以做,所以要么使用必需的初始化程序来实例化它,要么使所需的初始化程序不可用,或者使属性可变,这样你就可以有两个初始化程序,两者都可以初始化它。

答案 1 :(得分:0)

在调用super.init之前,必须在init方法中定义必需的属性。

因此,如果你想要一个必需的bookStore属性,并且想要覆盖init.coder方法,你需要在调用super.init之前为bookStore赋值:

required init(coder aDecoder: NSCoder) 
{
   bookStore = //some value here
   super.init(coder: aDecoder) 
}

可能最简单的方法是将bookStore属性设为可选的var:

var bookStore: BookStore?

如果这样做,您将不必在初始时为视图控制器的bookstore属性分配值,并且可以稍后在设置视图控制器以进行显示时执行此操作。

返回initWithCoder()

initWithCoder(或者是init(coder),因为它在Swift中调用)是一个应该反序列化对象的方法。

iOS使用initWithCoder从XIB文件和故事板中读取接口对象。

我们的想法是编写自定义版本的initWithCoder和encodeWithCoder,它们知道如何读取/写入对象的自定义属性,以便将其保存到文件中。

在encodeWithCoder中,您编写的代码将对象的自定义属性作为键/值对保存到归档器中。然后在initWithCoder中,使用NSKeyedUnarchiver的方法从归档程序中读取这些键/值对,以读取这些值。

答案 2 :(得分:0)

我不明白你为什么需要init,但规则是所有属性必须有值才能调用super.init(bookStore不会)。我想你可以解决这个问题     让bookStore = BookStore()