2015-02-06 125 views
3

UIViewController類定義了一個單一指定初始化,init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)和不便利初始化器,但是,它是可能寫入的代碼下面的行,並且具有其編譯(6.1.1的Xcode)UIViewController如何在Swift中設置默認的非參數初始值設定項?

let vc = UIViewController()

這是如何可能?

據雨燕的書,這裏有初始化繼承的規則

規則1如果你的子類沒有定義任何指定的初始化程序,它 自動繼承其所有超類指定初始化的。

規則2如果你的子類,要麼初始化通過繼承他們爲每 規則1提供其所有 超指定的一個實現,或通過提供一個自定義實現其 定義然後,它會自動繼承所有的一部分

摘錄自:蘋果公司「The Swift Programming Language。」iBooks。 https://itun.es/us/jEUH0.l

因此UIViewController不能繼承其祖先init()方法超類NSObject,那麼哪裏初始化從何而來?

在另一個說明中,因爲每個swift類必須最終調用它的指定初始化方法,那麼這是不是意味着initWithCoder:也最終會調用init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)?但是,實際情況似乎並非如此。

+1

它有一個'initWithCoder:'方法,因爲它符合'NSCoding',它需要它。不知道爲什麼它有一個默認的初始化器...因爲它是一個Objective-C類而不是Swift類,所以不需要遵循Swift繼承的規則,所以它不必調用指定的初始化器。如果你在Swift中重寫它,你可能不得不這樣做。迅速嘗試做的很大一部分是澄清許多這些奧術規則的例外。 – 2015-02-06 18:14:08

回答

3

Swift書中的規則適用於在Swift中定義的類。 UIViewController是從ObjC導入的一個類,因此它的行爲受ObjC規則(或缺乏)的支配。

在ObjC,指定初始化鏈模式是你應該 DO(不像斯威夫特在編譯器強制它的可以做的唯一的事情)。如果您調用繼承的初始化程序而不是指定的初始化程序,您將返回一個實例...但不能保證所述實例處於合理的狀態。 (實際上,你幾乎可以肯定它不會這樣。)ObjC類的作者有時會通過實現你不應該調用的初始化方法並讓它們拋出異常來實踐防禦性編碼,但這似乎不是這裏的情況。

這個特例可能是某種錯誤 - it wouldn't be a bad idea to file one with Apple。 Swift應該在從導入的ObjC API創建對象時執行初始化器規則(在這種情況下,UIViewController需要在ObjC中聲明其指定初始值設定項,NS_DESIGNATED_INITIALIZER),或者應該執行UIViewController以防止不正確的初始化。 (儘管有可能會有兼容性副作用來「修復」其中的任何一種。)

1

高於init功能註釋塊包含下列文字:

/* 
    The designated initializer. If you subclass UIViewController, you must call the super implementation of this 
    method, even if you aren't using a NIB. (As a convenience, the default init method will do this for you, 
    and specify nil for both of this methods arguments.) ... 
*/ 

這是我的理解是,因爲這是一個Objective-C類,允許隱式繼承的方法。如果你在swift中創建這個類的子類,你將無法訪問super.init()。如果您在Objective-C代碼中創建子類而不實現您自己的-[ init],則您的能夠使用()構建您的子類。

因爲您的項目會通過您所調用的類落入Objective-C域,因此可以找到選擇器。 Objective-C類的swift子類只能遵循快速繼承規則。

相關問題