2015-06-22 63 views
2

我正在製作應用程序來歸檔書籍,我正在勾上一個按鈕來保存數據,但我無法通過初始化。無法找出編碼器a解碼器:NSCoder

以下是錯誤的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 
    } 
} 
+0

你需要設置'self.bookStore'之前你調用'super.init' – dan

+0

我不明白我應該設置什麼它也。 BookStore是一個包含所有書籍和添加/刪除等的方法的類。 – aamck

回答

2

您的自定義初始值設定項無法初始化不可變屬性。如果你希望它是不可變的,那麼不用創建一個自定義的初始化器,只需要在需要的或指定的初始化器之一中進行初始化。

這樣,

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

但是,你的情況,你要爲你使用讓書店它是不可變的:圖書城,但如果你是不使用故事板,您可以簡單地從所需的初始化程序中拋出致命異常並使用您自己的初始化程序,

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() 

主要的理念在這裏,沒有兩個初始值設定初始化不可變屬性。只有一個可以做,所以要麼使用必需的初始化程序來實例化它,要麼使所需的初始化程序不可用,或者使該屬性可變,以便可以有兩個初始化程序,並且都可以初始化它。

+0

感謝您的回答。我將如何去實現這個功能,以便我可以在App Delegate中創建BookStore()。由於此刻每當我轉向不同的視圖並重新創建它時,所有數據都將丟失。我試圖修改它來像這樣工作,但我沒有太多的運氣。 – aamck

+0

你對這個視圖控制器使用storyboard嗎? – Sandeep

+0

是的,我做了,是什麼原因導致我所有的悲傷? – aamck

0

所需的屬性必須在init方法()你調用super之前定義。在裏面。

所以,如果你想有一個必要的書店屬性,要重寫init.coder方法,你需要一個值來書店調用super.init之前分配:

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

也許最簡單的要做的事情就是讓你的書店財產可選VAR:

var bookStore: BookStore? 

如果你這樣做,你就不必在初始時間值分配給您的視圖控制器的書店財產,可以在設置做到這一點以後用於顯示的視圖控制器。

回到initWithCoder()

的initWithCoder(或init(coder)如它被稱爲在SWIFT)是被認爲反序列化對象的方法。

iOS使用initWithCoder從XIB文件和故事板中讀取接口對象。

這個想法是,你編寫定製版本的initWithCoder和encodeWithCoder,知道如何讀/寫對象的自定義屬性,以便它可以保存到文件。

在encodeWithCoder中,您可以編寫代碼將對象的自定義屬性作爲鍵/值對保存到存檔器中。然後在initWithCoder中,您使用NSKeyedUnarchiver的方法從歸檔程序中讀取這些鍵/值對來讀取這些值。

0

我不明白你爲什麼需要init,但規則是在調用super.init(bookStore沒有)之前所有屬性都必須有值。我認爲你可以修復,就像 讓bookStore = BookStore()

相關問題