我是從網上課程學習iOS開發,每次我做一個自定義視圖(自定義表視圖細胞,採集觀察室等)的教練始終貫徹這個初始化:init編碼器aDecoder究竟是什麼?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
到底爲什麼總是我必須調用這個?它有什麼作用?我可以將屬性放入init嗎?
我是從網上課程學習iOS開發,每次我做一個自定義視圖(自定義表視圖細胞,採集觀察室等)的教練始終貫徹這個初始化:init編碼器aDecoder究竟是什麼?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
到底爲什麼總是我必須調用這個?它有什麼作用?我可以將屬性放入init嗎?
實現一個初始化的要求是兩件事情的結果:
的Liskov substitution principle。如果S是T的一個子類(例如,MyViewController
是ViewController
的子類),則S對象(MyViewController
的實例)必須能夠替換T對象(實例爲ViewController
)的位置。
如果在子類中明確定義了任何初始值設定項,則在Swift中不會繼承初始值設定項。如果明確提供了一個初始化程序,則必須明確提供所有其他初始化程序(然後纔可以撥打super.init(...)
)。基本原理見this question。它在Java中,但仍然適用。
到1點,一切原來ViewController
可以做什麼,MyViewController
子類應該是能夠做到的。一個這樣的事情是能夠從給定的NSCoder
初始化。到了第2點,你的MyViewController
子類不會自動繼承這個能力。因此,您必須手動提供符合此要求的初始化程序。在這種情況下,你只需要將它委託給超類,讓它做它通常會做的事情。
構造函數不被繼承是非常有意義的:如果使用基類的(繼承)初始化方法初始化派生類的實例,那麼派生類新定義(「添加」)的非繼承屬性將會永遠不會被初始化。 –
實際上,初始值設定項是在Swift中繼承的,因爲您沒有在您的子類中提供任何自己的初始值設定項實現。如果新定義的非繼承屬性具有默認值,那麼可以避免在子類中編寫任何初始化器,並簡單地繼承所有超類的初始化器。見[這裏](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID222) – TheBaj
@TheBaj好點,我忽略了這一點。 – Alexander
我會從相反的方向開始回答:如果要將視圖的狀態保存到磁盤,該怎麼辦?這被稱爲系列化。反過來是反序列化 - 從磁盤恢復對象的狀態。
的NSCoding
協議定義了2種方法進行序列化和反序列化對象:
encodeWithCoder(_ aCoder: NSCoder) {
// Serialize your object here
}
init(coder aDecoder: NSCoder) {
// Deserialize your object here
}
那麼,爲什麼需要它在你的自定義類?答案是Interface Builder。將對象拖放到故事板並對其進行配置時,Interface Builder會將該對象的狀態序列化到磁盤上,然後在故事板出現在屏幕上時將其反序列化。您需要告訴Interface Builder如何執行這些操作。至少,如果您沒有爲您的子類添加任何新屬性,則可以直接要求超類爲您進行打包和解包,因此請致電super.init(coder: aDecoder)
。如果你的子類更復雜,你需要爲子類添加你自己的序列化和反序列化代碼。
這與Visual Studio的方法形成鮮明對比,該方法將代碼寫入隱藏文件以在運行時創建對象。
這個答案會幫助你http://stackoverflow.com/questions/24036393/fatal-error-use-of-unimplemented-initializer-initcoder-for-class謝謝 –
如果你實現了一個實現了'NSCoding'的對象,那麼你需要實現這個初始化器,因爲它需要實現'NSCoding'的類。您至少必須調用超類init方法。如果'NSCoder'包含你的類的編碼屬性,那麼你可以使用這種方法來恢復那些 – Paulw11
嘗試搜索。這個問題在這裏已經被回答了很多次。 – matt