致命错误:类使用未实现的初始化器'init(coder:)'。

157

我决定继续使用Swift完成剩余的项目。当我将自定义类(UIViewcontroller的子类)添加到我的storyboard视图控制器并加载项目时,应用程序突然崩溃,并显示以下错误:

致命错误:对于类而言,未实现初始化程序'init(coder:)'的使用

这是代码:

import UIKit

class TestViewController: UIViewController {

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Custom initialization
    }

    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.
    }

    /*
    // #pragma 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.
    }
    */
}

请提出建议

6个回答

211

问题

这是由于目标UIViewController缺少初始化程序init?(coder aDecoder: NSCoder)导致的。因为从UIStoryboard实例化一个UIViewController时会调用该方法。

要了解如何从UIStoryboard初始化UIViewController,请在此处查看

为什么Objective-C没有这个问题?

因为Objective-C自动继承所有必需的UIViewController初始化程序。

为什么Swift不自动继承初始化程序?

Swift默认情况下不继承初始化程序,这是出于安全考虑。但如果所有属性都有值(或可选),并且子类没有定义任何指定的初始化程序,则它将继承超类的所有初始化程序。


解决方案

1. 第一种方法

在目标UIViewController上手动实现init?(coder aDecoder: NSCoder)

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

2. 第二种方法

在您的目标UIViewController上删除init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)将从超类继承所有所需的初始化程序,正如Dave Wood在他下面的答案中指出的那样。



4
谢谢您的提问。快速回复如下:当您创建TableViewController文件时,Xcode已经包含了 `init(style: UITableViewStyle){ super.init(style: style) // Custom initialization }`的代码。为什么我们可以有两个init函数?任何关于苹果为什么不默认包含第二个init函数的想法吗? - Trevor McKendrick
这与iOS 7或iOS 8无关。这与Swift继承初始化程序的方式有关! - Sulthan
公共初始化方法(view: UIViewController, frame: CGRect){ self.viewController = view self.imageName = "" self.actionName = "" super.init(frame: frame) } - scrainie
第一种方法奏效了!我的动态表格终于填满了动态单元格!!!这都是因为fatalError("init(coder:) has not been implemented")这行代码使我的应用程序停止了。 - Jose Manuel Abarca Rodríguez

26

除了 @3r1d 提出的方法外,另一种选择是从您的类中删除以下 init 方法:

init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    // Custom initialization
}

包括那个init方法,可以防止子类继承它的超类init(coder aDecoder: NSCoder!)。不包括它,你的类将继承它们两个。

注意:有关更多详细信息,请参见WWDC 2014会话403“Intermediate Swift”,大约在33:50处。


感谢您指出关于Session 403的解释。但是,如果子类只有便利初始化程序,则它将继承超类初始化程序,对吗? - jamiltz
1
是的。只有在提供自己的指定初始化方法(调用超类初始化方法的方法)时,才会防止超类初始化方法被继承。然后,您必须通过将它们添加到您的类并仅调用超级版本来指定要支持哪些超级初始化方法(如@3r1d的答案中所示)。 - Dave Wood
在您的子类中只有 convenience init() 而没有 (designated) init() 将导致编译错误。这是因为 convenience init() 函数必须在函数定义内部调用 self.init()。 - Ohmy
@narumolPug 这是不正确的。您不需要包括指定的 init 方法。您的子类将从超类继承它们。您仍然可以调用 self.init(),这将执行超级版本。 - Dave Wood
视频的确切时刻可以在这里找到:https://youtu.be/W1s9ZjDkSN0?t=2030 - mfaani

10

对于遇到Swift UICollectionViewCells 相同问题的人,请将 @3r1d 建议的代码添加到您自定义的 UICollectionViewCell 类中,而不是视图控制器中:

init(coder aDecoder: NSCoder!)
{
    super.init(coder: aDecoder)
}

你指的是哪个UICollectionViewCell?使用编码器进行初始化是初始化视图控制器的方法。 - E-Riddie
在编程中,如果有人遇到问题(我就遇到了)... 如果你尝试使用UICollectionViewController,在你的自定义单元格.swift文件中,你需要放置init with coder。 - Nick Yap
2
每次使用这种实例化方式时,您都需要添加此代码。https://dev59.com/OGAg5IYBdhLWcg3wDHQ3#24036227 - E-Riddie

3

对于需要Swift代码的人:

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

[编辑] 这是针对旧版本Swift的。可能不再适用。


3
我在一个编程的collectionView单元格中遇到了这个问题,尽管op询问的是vc,但当我搜索答案时仍然找到了这个问题。对我来说,问题是我确实有一个

标签,但它不应该在那里。
required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

我实现了顶部答案无法使用的方法。我在单元格中没有初始化器:

// my programmatic cell was missing this
override init(frame: CGRect) {
    super.init(frame: frame)
}

当我添加它时,错误消失了。


1
与其添加一些使内部机制正常工作的方法,我会定义我的属性为@lazy并在类范围内进行初始化。

你也可以通过 ? 将属性声明为可选的。 - Julian B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接