2014-09-28 88 views
3

爲什麼UIViewController子類的Swift默認初始化程序init()初始化屬性兩次?同樣的事情發生在UIView的子類中,但與NSObject的直接子類不同。爲什麼UIViewController子類的Swift默認初始化程序初始化屬性兩次?

通過使用Parent(nibName: nil, bundle: nil)而不是Parent()進行初始化,問題消失。當我爲Parent提供自定義初始化程序時,它也能正常工作。

我知道如何解決這個問題,但我很好奇它爲什麼會發生。

該問題可通過將此代碼複製到Xcode 6.0.1 Playground進行復制。

import UIKit 

class Child { 
    init() { 
     println("Child init") 
    } 
} 

class Parent: UIViewController { 
    let child = Child() 
} 

// This way "Child init" is printed twice: 
let parent = Parent() 

// This way "Child init" is printed once: 
//let parent = Parent(nibName: nil, bundle: nil) 



更新:當我定義了具有相似初始化像那些UIViewController擁有和使用,作爲Parent左右逢源超初始化它只是工作,並打印「孩子初始化」假類一旦。

import UIKit 

class Child { 
    init() { 
     println("Child init") 
    } 
} 

class FakeViewController : UIResponder { 
    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { 

    } 

    convenience override init() { 
     self.init(nibName: nil, bundle: nil) 
    } 
} 

class Parent: FakeViewController { 
    let child = Child() 
} 

// With the FakeViewController both initializers cause "Child init" to be printed once: 
let parent = Parent() 
//let parent = Parent(nibName: nil, bundle: nil) 


  • 是UIViewController的便利的init()應該工作的方式?
  • 在UIViewController的便捷init()的實現中是否存在缺陷?
  • 是init()UIViewController的有效初始值設定項嗎?也許它不是和let parent = Parent()在第一個例子中甚至不應該編譯?
+0

請參閱UIViewController中的文檔,以及在繼承它時需要提供的內容。通過插入FakeViewController,您正在使用以下建議來解決問題。 – AlBlue 2014-09-28 15:43:24

回答

0

此問題已在Xcode 6.3中修復。我可以重現錯誤的最後一個版本是Xcode 6.2。

3

構建父實例時首次打印;所有實例字段都會在該位置初始化,其中包括創建Child實例。

當隱式super.init被稱爲父節點時,會發生第二次打印。鑑於此代碼已關閉,因此無法確切知道發生了什麼;但問題可能源於initUIViewcontroller(指定的初始化程序爲init:nibName:bundle)中的便利初始值設定項這一事實。 UIVIewController中的文檔聲明,當它被覆蓋時,必須調用必需的初始化器。

因此,要解決這個問題,你需要添加:

class Parent: UIViewController { 
    override init() { 
    super.init(nibName:nil,bundle:nil) 
    } 
    // the following is also required if implementing an initializer 
    required init(coder:NSCoder) { 
    super.init(coder:coder) 
    } 
} 

更多信息請參見https://developer.apple.com/library/prerelease/iOS/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_319關於指定VS便利的初始化。

+0

我收到錯誤「初始化程序不重寫指定的初始化程序從它的超類」的行「覆蓋init(){」 – user1021430 2015-06-10 18:35:07

1

顯然,UIViewContollerinit實現,如:

- (instancetype)init { 
    self = [super init]; // <- not sure 
    if(self) { 
     self = [[self.class alloc] initWithNibName:nil bundle:nil]; 
    } 
    return self; 
} 

可以看到,與調試器,那的Parentself具有第一Child()呼叫和第二個之間不同的地址。

在Swift中,屬性初始化爲之前所有者對象被初始化。這就是爲什麼你的Child()被調用兩次。