2015-06-22 94 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()

相关问题