Ios 无法以编程方式在Swift中创建UIViewController

Ios 无法以编程方式在Swift中创建UIViewController,ios,cocoa-touch,swift,uiviewcontroller,initializer,Ios,Cocoa Touch,Swift,Uiviewcontroller,Initializer,当我尝试在Swift中创建UIViewController的实例时,所有继承的初始化器都不可用,即使我没有在视图控制器(或任何其他,FWIW)中定义任何指定的init 此外,如果我试图通过将其设置为根视图控制器来显示它,则它永远不会显示: func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

当我尝试在
Swift
中创建
UIViewController
的实例时,所有继承的初始化器都不可用,即使我没有在视图控制器(或任何其他,FWIW)中定义任何指定的init

此外,如果我试图通过将其设置为根视图控制器来显示它,则它永远不会显示:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.

        window = UIWindow(frame: UIScreen.mainScreen().bounds)
        window?.makeKeyAndVisible()
        window?.backgroundColor = UIColor.greenColor()



        let vc = ImageViewController()
        window?.rootViewController = vc

        return true
    }
视图控制器的代码只是Xcode的模板:

import UIKit

class ImageViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */

}

有人知道发生了什么吗???

正如您所指出的:只要nib名称与objective-C中的类名匹配,即使您在初始化视图控制器时没有指定nib名称,视图控制器仍将继续运行

但出于某种原因(可能是一个bug),Swift中的情况并非如此

而不是写:

let vc = ImageViewController()
初始化视图控制器时,必须显式指定接口:

let vc = ImageViewController(nibName: "nibName", bundle: nil)

为了方便起见,我提出了这个解决方法,这样我就不必到处使用较长的初始值设定项。我有一个
BaseViewController
,我的所有控制器都扩展了它

init () {
    let className = NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last
    super.init(nibName: className, bundle: NSBundle(forClass: self.dynamicType))
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}
注意,使用
NSBundle(forClass:self.dynamicType)
可以处理不同目标中的名称空间

然后,当我想实例化一个
ViewController
时,我会像在Objective-C中一样使用
MyViewController()

let Vc = UIViewController()
vc.view = yourview
或将以上vc添加到作为ChildviewController查看

configureChildViewController(vc,onView:yourview in Viewcontroller)
将此扩展用于UiViewController

extension UIViewController {


func configureChildViewController(childController: UIViewController, onView: UIView?) {
    var holderView = self.view
    if let onView = onView {
        holderView = onView
    }
    addChildViewController(childController)
    holderView.addSubview(childController.view)
    constrainViewEqual(holderView, view: childController.view)
    childController.didMoveToParentViewController(self)
}

func scatterChildViewController(childController: UIViewController) {
    childController.willMoveToParentViewController(self)
    childController.view.removeFromSuperview()
    childController.removeFromParentViewController()
}

func constrainViewEqual(holderView: UIView, view: UIView) {
    view.translatesAutoresizingMaskIntoConstraints = false
    //pin 100 points from the top of the super
    let pinTop = NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal,
        toItem: holderView, attribute: .Top, multiplier: 1.0, constant: 0)
    let pinBottom = NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal,
        toItem: holderView, attribute: .Bottom, multiplier: 1.0, constant: 0)
    let pinLeft = NSLayoutConstraint(item: view, attribute: .Left, relatedBy: .Equal,
        toItem: holderView, attribute: .Left, multiplier: 1.0, constant: 0)
    let pinRight = NSLayoutConstraint(item: view, attribute: .Right, relatedBy: .Equal,
        toItem: holderView, attribute: .Right, multiplier: 1.0, constant: 0)

    holderView.addConstraints([pinTop, pinBottom, pinLeft, pinRight])
}

}

您是否尝试过实现所需的init(coder-aDecoder:NSCoder!)?我刚刚实现了,然后它将识别唯一的init。然而,我不需要它。我想要self.init(nibName:nil,bundle:nil)。出于某种原因,所有继承的初始值设定项似乎都丢失了,即使我没有向UIViewControllert的子类添加指定的init。问题是您正在创建一个nil vc。你使用的是故事板还是NIB?我使用的是NIB,但它看起来不像是nil:po vc 0x00007fa742b00000{UIKit.UIViewController={UIKit.UIResponder={ObjectiveC.NSObject={}}}nil是个错误的词。。。我的意思是没有界面的vc。好吧,现在它可以工作了。:-)如果我显式地调用nibName:,bundle:初始值设定项(即使autocomplete无法识别它),并传递xib文件的名称,它就会工作。但是,这不是预期的行为:如果我只调用init或init(nibName:nil,bundle:nil),它应该通过查看类的名称来获取xib文件的名称。但事实并非如此:-(@cfisher但是你的init在哪里?我没有在视图控制器中定义任何init。代码正是Xcode模板提供的代码。它是问题末尾包含的代码。我从我的ApplicationLegate调用它,在应用程序中,它确实使用options方法完成了加载。@cfisher好的,那就是你的问题。不管怎样,w无论是在你的应用程序委托中还是在自定义初始化中,你100%都必须显式地传递/包含你的xib文件的名称。不是“它应该通过查看类的名称来获取xib文件的名称。”甚至苹果公司也在他们的docs::init中将上述方法列为“为视图控制器类指定初始化”(nibName nibName:String?,bundle NIBNUDLE:NSBundle?)确实是UIViewControllers的指定初始值设定项。但是,您不必为nib文件指定名称,除非nib文件的名称与类的名称不同。