xcode 在 ios 8 beta 5 中,带有 nib 文件的视图控制器是否损坏?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25149604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are view controllers with nib files broken in ios 8 beta 5?
提问by Jim T
I created a test project in ios 8 beta 4 which as a main view controller and a second view controller created as a UIViewController subclass with a xib file.
我在 ios 8 beta 4 中创建了一个测试项目,它作为主视图控制器和第二个视图控制器,创建为带有 xib 文件的 UIViewController 子类。
I put a button on the main controller to present the second controller:
我在主控制器上放了一个按钮来呈现第二个控制器:
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.
}
}
}
I run the app and pressing the button presents the second controller - all is well
我运行应用程序并按下按钮显示第二个控制器 - 一切都很好
Moving to xcode beta 5, I run the app and when I press the button the screen goes black.
转到 xcode beta 5,我运行该应用程序,当我按下按钮时,屏幕变黑。
Since I know they messed with the init code, I tried putting in overrides to see it that would fix it:
因为我知道他们弄乱了 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.
}
Same problem. Changing the required and overrides in to all possible combinations accepted by xcode has no effect.
同样的问题。将 required 和 overrides 更改为 xcode 接受的所有可能组合无效。
If I use the storyboard to create another controller and segue to it all is well.
如果我使用故事板创建另一个控制器并继续使用它,一切都很好。
Any ideas?
有任何想法吗?
EDIT - New info
编辑 - 新信息
- Tried nibName = nil in init - same problem
- Created the same app in objective c and it works fine
- 在 init 中尝试了 nibName = nil - 同样的问题
- 在目标 c 中创建了相同的应用程序,它运行良好
Apparently a swift beta 5 problem
显然是一个 swift beta 5 问题
回答by matt
I can't tell whether it's a bug or not, but it is definitely a change. Of course they might change it back... In any case, the rule in seed 5 is:
我不知道这是否是一个错误,但这绝对是一个变化。当然,他们可能会改回来……无论如何,种子 5 中的规则是:
The view controller will notautomatically find its .xib just because it has the same name. You have to supply the name explicitly.
视图控制器不会仅仅因为它具有相同的名称就自动找到它的 .xib。您必须明确提供名称。
So in your case any attempt to initialize this view controller must ultimately call nibName:bundle:
with an explicit nib name ("TestVC"
), I assume.
因此,在您的情况下,我假设任何初始化此视图控制器的尝试最终都必须nibName:bundle:
使用显式笔尖名称 ( "TestVC"
) 进行调用。
If you want to be able to initialize by calling
如果您希望能够通过调用进行初始化
let vc = TestVC()
as you are doing in your presenting view controller, then simply override init()
in the presented view controller to call super.init(nibName:"TestVC", bundle:nil)
and that's all you need (except that I presume you will also need the init(coder:)
stopper discussed here).
正如您在呈现视图控制器中所做的那样,然后只需覆盖init()
呈现的视图控制器以进行调用super.init(nibName:"TestVC", bundle:nil)
,这就是您所需要的(除了我认为您还需要此处init(coder:)
讨论的塞子)。
EDITYou are absolutely right that this is a Swift-only problem. Well spotted. In Objective-C, initializing with init
(or new
) still works fine; the view controller finds its eponymous .xib file correctly.
编辑您完全正确,这是一个仅限 Swift 的问题。好眼力。在 Objective-C 中,使用init
(or new
)初始化仍然可以正常工作;视图控制器正确地找到了它的同名 .xib 文件。
ANOTHER EDITThe determining factor is not whether Objective-C or Swift calls init
. It is whether the view controller itselfis written in Objective-C or Swift.
另一个编辑决定因素不是 Objective-C 还是 Swift 调用init
。这取决于视图控制器本身是用 Objective-C 还是 Swift 编写的。
FINAL EDITThe workaround is to declare your Swift view controller like this:
最终编辑解决方法是像这样声明你的 Swift 视图控制器:
@objc(ViewController) ViewController : UIViewController { // ...
The name in parentheses gets rid of the name mangling which is causing the problem. It is likely that in the next release this will be fixed and you can take the @objc
away again.
括号中的名称消除了导致问题的名称修饰。很可能在下一个版本中,这将得到修复,您可以@objc
再次删除。
ANOTHER FINAL EDITBad news: the bug report I filed on this came back "works as intended". They point out that all I have to do is name the .xibfile after the surrounding module, e.g. if my app is called NibFinder, then if I name my .xibfile NibFinder.ViewController.xib, it will be found automatically when instantiating ViewController()
.
另一个最终编辑坏消息:我提交的错误报告“按预期工作”回来了。他们指出,所有我需要做的就是命名的.xib周边模块后的文件,例如,如果我的应用程序被称为NibFinder,那么如果我的名字我的.xib文件NibFinder.ViewController.xib实例化时,它会自动找到ViewController()
。
That is true enough, but in my view it merely restates the bug; the Swift lookup procedure is prepending the module name. So Apple is saying I should knuckle under and prepend the same module name to my .xibfile, whereas I am saying that Apple should knuckle under and strip the module name off as it performs the search.
这是事实,但在我看来,它只是重申了错误;Swift 查找过程在模块名称之前。所以 Apple 说我应该在我的.xib文件中加入相同的模块名称,而我是说 Apple 应该在执行搜索时加入并去除模块名称。
EDIT THAT IS TRULY TRULY FINALThis bug is fixed in iOS 9 beta 4 and all these workarounds become unnecessary.
真正最终的编辑此错误已在 iOS 9 beta 4 中修复,所有这些变通方法都变得不必要了。
回答by Alex
in case if You need support of iOS8. You can use extension on UIViewController
如果您需要 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)
}
}
and then, just create the instance this way
然后,以这种方式创建实例
let vc = TestVC.instanceWithDefaultNib()
回答by Francesco Ceravolo
This trick works for me. If you have a base view controller class you can override the nibName property returning the class name (equals to the xib file name).
这个技巧对我有用。如果您有一个基本视图控制器类,您可以覆盖返回类名(等于 xib 文件名)的 nibName 属性。
class BaseViewController: UIViewController {
override var nibName: String? {
get {
guard #available(iOS 9, *) else {
let nib = String(self.classForCoder)
return nib
}
return super.nibName
}
}
}
All view controllers that inherit from this base class could load their xib. e.g. MyViewController: BaseViewController could load MyViewController.xib
从这个基类继承的所有视图控制器都可以加载它们的 xib。例如 MyViewController: BaseViewController 可以加载 MyViewController.xib
回答by yinpan
I've had this problem recently, and my solution is to override the nibName method in baseviewController. My solution is as follows:
我最近遇到了这个问题,我的解决方案是覆盖 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
}
}
}
回答by Ralf Ebert
I had a very similar problem on Xcode 10.1 and iOS 12.
我在 Xcode 10.1 和 iOS 12 上遇到了非常相似的问题。
This code worked:
此代码有效:
class ExampleViewController: UIViewController {
init() {
super.init(nibName: "ExampleViewController", bundle: nil)
}
}
But passing nil as nibName
made it not load the XIB.
When specifying the class name explicitly via @objc("ExampleViewController") this fixed it.
但是传递 nilnibName
使其不加载 XIB。当通过 @objc("ExampleViewController") 显式指定类名时,它修复了它。
The problem was caused by the module name starting with the letters 'UI' (the project was called UIKitExample). When I renamed the target to something else, this fixed the problem.
问题是由以字母“UI”开头的模块名称引起的(该项目名为 UIKitExample)。当我将目标重命名为其他内容时,这解决了问题。
回答by KaterinaPetrova
Here's code, based on Francesco answer. It contains check if nib file exits, so app will not crashed when you load UIViewController which doesn't have associated xib (you can reproduce it on iOS8)
这是基于 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
}
}
回答by Zander Zhang
Swift3:
斯威夫特3:
extension UIViewController {
static func instanceWithDefaultNib() -> Self {
let className = NSStringFromClass(self).components(separatedBy: ".").last
return self.init(nibName: className, bundle: nil)
}
}