2014-09-28 90 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()被调用两次。