在ios 8 beta 5中是否损坏了带有nib文件的视图控制器?

时间:2014-08-05 22:53:11

标签: ios xcode

我在ios 8 beta 4中创建了一个测试项目,它作为主视图控制器和第二个视图控制器创建为带有xib文件的UIViewController子类。

我在主控制器上放了一个按钮来显示第二个控制器:

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

@IBAction func testVCBtnTapped() {
    let vc = TestVC()
    presentViewController(vc, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

我运行应用程序并按下按钮显示第二个控制器 - 一切都很好

转到xcode beta 5,我运行应用程序,当我按下按钮时,屏幕变黑。

因为我知道他们搞砸了init代码,所以我尝试使用覆盖来查看它会修复它:

class TestVC: UIViewController {

override init() {
    super.init()
}
required init(coder aDecoder: NSCoder!) {
    super.init(coder: aDecoder)
}
override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

override func viewDidLoad() {
    super.viewDidLoad()

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

同样的问题。将所需和覆盖更改为xcode接受的所有可能组合无效。

如果我使用故事板创建另一个控制器并且转向它一切都很好。

有什么想法吗?

编辑 - 新信息

  1. 在init中尝试了nibName = nil - 同样的问题
  2. 在目标c中创建了相同的应用,并且工作正常
  3. 显然是一个快速的beta 5问题

7 个答案:

答案 0 :(得分:25)

我不知道这是不是一个错误,但它肯定是一个变化。当然,他们可能会改变它......无论如何,种子5中的规则是:

视图控制器将自动查找其.xib,因为它具有相同的名称。您必须明确提供名称。

因此,在您的情况下,任何初始化此视图控制器的尝试都必须最终使用显式的笔尖名称(nibName:bundle:)调用"TestVC",我认为。

如果您希望能够通过调用

进行初始化
let vc = TestVC()

正如您在呈现视图控制器中所做的那样,只需在呈现的视图控制器中覆盖init()即可调用super.init(nibName:"TestVC", bundle:nil),这就是您所需要的(除了我认为您还需要{{} 1}}塞子讨论了here)。

编辑你绝对正确,这是一个仅限Swift的问题。好眼力。在Objective-C中,使用init(coder:)(或init)初始化仍然可以正常工作;视图控制器正确找到它的同名.xib文件。

另一个编辑决定因素不是Objective-C或Swift是否调用new视图控制器本身是用Objective-C还是Swift编写的。

最终编辑解决方法是声明您的Swift视图控制器:

init

括号中的名称消除了导致问题的名称错误。可能在下一个版本中,这将被修复,您可以再次将@objc(ViewController) ViewController : UIViewController { // ... 带走。

另一个最终编辑坏消息:我提交的错误报告回来了“按预期工作”。他们指出,我所要做的就是在周围模块之后命名 .xib 文件,例如:如果我的应用程序名为 NibFinder ,那么如果我将 .xib 文件命名为 NibFinder.ViewController.xib ,则在实例化时会自动找到它{ {1}}。

这是真的,但在我看来,它只是重述了这个错误; Swift查找过程在模块名称前面加上。因此,苹果公司表示我应该为我的 .xib 文件添加并添加相同的模块名称,而我说Apple应该关闭并在执行搜索时删除模块名称。

编辑真的很棒这个错误在iOS 9 beta 4中得到修复,所有这些变通办法都变得不必要了。

答案 1 :(得分:4)

如果您需要iOS8的支持。 您可以在UIViewController上使用扩展

extension UIViewController {
    static func instanceWithDefaultNib() -> Self {
        let className = NSStringFromClass(self as! AnyClass).componentsSeparatedByString(".").last
        let bundle = NSBundle(forClass: self as! AnyClass)
        return self.init(nibName: className, bundle: bundle)
    }
}

然后,只需以这种方式创建实例

let vc = TestVC.instanceWithDefaultNib()

答案 2 :(得分:3)

这个技巧对我有用。如果您有基本视图控制器类,则可以覆盖返回类名的nibName属性(等于xib文件名)。

class BaseViewController: UIViewController {

   override var nibName: String? {
      get {
         guard #available(iOS 9, *) else {
            let nib = String(self.classForCoder)
            return nib
         }

         return super.nibName
       }
    }
}

从此基类继承的所有视图控制器都可以加载其xib。 例如MyViewController:BaseViewController可以加载MyViewController.xib

答案 3 :(得分:2)

我最近遇到了这个问题,我的解决方案是重写baseviewController中的nibName方法。我的解决方法如下:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

init() {
    super.init(nibName: nil, bundle: Bundle.main)
}

override var nibName: String? {
    get {
        if #available(iOS 9, *) {
            return super.nibName
        } else {
            let classString = String(describing: type(of: self))
            guard Bundle.main.path(forResource: classString, ofType: "nib") != nil else {
                return nil
            }
            return classString
        }
    }
}

答案 4 :(得分:0)

这是基于Francesco答案的代码。它包含检查nib文件是否退出,因此当你加载没有关联xib的UIViewController时你不会崩溃(你可以在iOS8上重现它)

override var nibName: String? {
    get {
        let classString = String(describing: type(of: self))
        guard nibBundle?.path(forResource: classString, ofType: "nib") != nil else {
            return nil
        }
        return classString
    }
}
override var nibBundle: Bundle? {
    get {
        return Bundle.main
    }
}

答案 5 :(得分:0)

Swift3:

Cars
belongs_to :car_city

CarCities
has_many :cars

答案 6 :(得分:0)

我在Xcode 10.1和iOS 12上遇到了非常相似的问题。

此代码有效:

class ExampleViewController: UIViewController {

    init() {
        super.init(nibName: "ExampleViewController", bundle: nil)
    }

}

但是将nil传递为nibName使其无法加载XIB。 通过@objc(“ ExampleViewController”)显式指定类名时,此问题已得到解决。

问题是由以字母“ UI”开头的模块名称引起的(该项目称为UIKitExample)。当我将目标重命名为其他名称时,此问题得以解决。