Swift Thread 1: Fatal error: init(coder:) has not been implemented (调用超级解决方案不起作用)

Posted

技术标签:

【中文标题】Swift Thread 1: Fatal error: init(coder:) has not been implemented (调用超级解决方案不起作用)【英文标题】:Swift Thread 1: Fatal error: init(coder:) has not been implemented (Calling super solution doesn't work) 【发布时间】:2018-01-10 17:24:51 【问题描述】:

大家好,我已经四处搜索,但仍然找不到解决问题的方法。我这里有一个自定义类:

import UIKit

/** 
  DatasourceController is simply a UICollectionViewController that 
allows you to quickly create list views.

 In order to render our items in your list, simply provide it with a 
Datasource object.
 */
open class DatasourceController: UICollectionViewController, 
UICollectionViewDelegateFlowLayout 

open let activityIndicatorView: UIActivityIndicatorView = 
    let aiv = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
    aiv.hidesWhenStopped = true
    aiv.color = .black
    return aiv
()

open var datasource: Datasource? 
    didSet 
        if let cellClasses = datasource?.cellClasses() 
            for cellClass in cellClasses 
                collectionView?.register(cellClass, forCellWithReuseIdentifier: NSStringFromClass(cellClass))
            
        

        if let headerClasses = datasource?.headerClasses() 
            for headerClass in headerClasses 
                collectionView?.register(headerClass, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: NSStringFromClass(headerClass))
            
        

        if let footerClasses = datasource?.footerClasses() 
            for footerClass in footerClasses 
                collectionView?.register(footerClass, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: NSStringFromClass(footerClass))
            
        

        collectionView?.reloadData()
    


public init() 
    super.init(collectionViewLayout: UICollectionViewFlowLayout())


required public init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


let defaultCellId = "lbta_defaultCellId"
let defaultFooterId = "lbta_defaultFooterId"
let defaultHeaderId = "lbta_defaultHeaderId"

override open func viewDidLoad() 
    super.viewDidLoad()
    collectionView?.backgroundColor = .white
    collectionView?.alwaysBounceVertical = true

    view.addSubview(activityIndicatorView)
    activityIndicatorView.anchorCenterXToSuperview()
    activityIndicatorView.anchorCenterYToSuperview()

    collectionView?.register(DefaultCell.self, forCellWithReuseIdentifier: defaultCellId)
    collectionView?.register(DefaultHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: defaultHeaderId)
    collectionView?.register(DefaultFooter.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: defaultFooterId)


override open func numberOfSections(in collectionView: UICollectionView) -> Int 
    return datasource?.numberOfSections() ?? 0


override open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return datasource?.numberOfItems(section) ?? 0


//need to override this otherwise size doesn't get called
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
    return CGSize(width: view.frame.width, height: 50)


override open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

    let cell: DatasourceCell

    if let cls = datasource?.cellClass(indexPath) 
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
     else if let cellClasses = datasource?.cellClasses(), cellClasses.count > indexPath.section 
        let cls = cellClasses[indexPath.section]
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
     else if let cls = datasource?.cellClasses().first 
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
     else 
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: defaultCellId, for: indexPath) as! DatasourceCell
    

    cell.controller = self
    cell.datasourceItem = datasource?.item(indexPath)
    return cell


override open func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView 

    let reusableView: DatasourceCell

    if kind == UICollectionElementKindSectionHeader 
        if let classes = datasource?.headerClasses(), classes.count > indexPath.section 
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: NSStringFromClass(classes[indexPath.section]), for: indexPath) as! DatasourceCell
         else if let cls = datasource?.headerClasses()?.first 
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
         else 
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: defaultHeaderId, for: indexPath) as! DatasourceCell
                    
        reusableView.datasourceItem = datasource?.headerItem(indexPath.section)

     else 
        if let classes = datasource?.footerClasses(), classes.count > indexPath.section 
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: NSStringFromClass(classes[indexPath.section]), for: indexPath) as! DatasourceCell
         else if let cls = datasource?.footerClasses()?.first 
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: NSStringFromClass(cls), for: indexPath) as! DatasourceCell
         else 
            reusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: defaultFooterId, for: indexPath) as! DatasourceCell
        
        reusableView.datasourceItem = datasource?.footerItem(indexPath.section)
    

    reusableView.controller = self

    return reusableView


open func getRefreshControl() -> UIRefreshControl 
    let rc = UIRefreshControl()
    rc.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
    return rc


@objc open func handleRefresh() 



open var layout: UICollectionViewFlowLayout? 
    get 
        return collectionViewLayout as? UICollectionViewFlowLayout
    

这是我故事板中 UICollectionView 控制器的父类。我在这里为它创建了一个控制器类:

import LBTAComponents

class homeView: DatasourceController 

override func viewDidLoad() 
    super.viewDidLoad()


required init?(coder aDecoder: NSCoder) 
fatalError("init(coder:) has not been implemented")


 

问题我得到 Thread 1: Fatal error: init(coder:) has not been implemented when running this code 我已经尝试过解决方案:

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

这不起作用。还有其他建议吗?如果您想亲自查看,我从 cocoapod 库中获得了这个框架:

pod 'LBTAComponents'

我怀疑这个问题与集合视图和情节提要有关,但我无法弄清楚。

【问题讨论】:

你甚至不需要那个required init?(coder aDecoder。删掉就好了。 我同意。删除不需要的初始化程序。 @creeperspeak 我摆脱了它.. 仍然得到同样的错误刚才错误来自 dataSourceController 类:( 在 DatasourceController 中也删除它。请注意,无论谁编写了原创课程,他并不打算首先将它提供给 Storyboard/XIB 的用户。 @MichaelVorontsov 它是必需的,我无法删除它:(:必需的初始化程序 'init(coder:)' 必须由 'UICollectionViewController' 的子类提供 【参考方案1】:

每当 ViewController 从 Storyboard/XIB 初始化时,它都是由init(coder: ) 完成的

您的基类 DatasourceController 覆盖初始化程序

public init() 
    super.init(collectionViewLayout: UICollectionViewFlowLayout())


required public init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")

所以当你在 HomeController 中调用 super.init(coder:...) 时,它实际上会调用 fatalError("init(coder:) has not been implemented") 似乎写这个类的人不是一个伟大的故事板/xib 爱好者。

您可以删除删除 DatasourceController 中的两个初始化程序,但请确保您在情节提要中设置了 Flow 布局。或者您可以将它们更改为调用 super。

如果你不能改变基类,你就不能从 Storyboard 加载你的 VC。

【讨论】:

作为解决方法,您仍然在情节提要中放置空白 VC,并在其 viewDidLoad 中初始化您的 HomeVC 并添加它,并将其作为子视图。

以上是关于Swift Thread 1: Fatal error: init(coder:) has not been implemented (调用超级解决方案不起作用)的主要内容,如果未能解决你的问题,请参考以下文章

Err "Kernel panic - not syncing: Fatal exception"

[ERR] collect2: fatal error: cannot find 'ld'

VS2010中调试程序是错误:fatal error C1083: 无法打开包括文件:“thread”

FATAL EXCEPTION: Thread-7890 java.lang.ExceptionInInitializerError

dyld:未找到符号:_ERR_remove_thread_state

java.lang.NoSuchMethodError E / AndroidRuntime:FATAL EXCEPTION:Thread-4进程:com.hikvision.open.app,PID