【问题标题】:Missing argument for parameter 'coder' in call when presenting a view from CollectionViewCell从 CollectionViewCell 呈现视图时,调用中缺少参数“coder”的参数
【发布时间】:2022-01-28 23:44:28
【问题描述】:

我有一个内部带有 CollectionView 的 ViewController 和一个带有 TableView 内部的 CollectionViewCell。当用户单击 TableViewCell 时,我想显示一个 ViewController 来显示用户任务的详细视图,但我在此行 let vc = MyTasksDetailController() 处收到此错误“调用中的参数 'coder' 缺少参数”。 这是我的代码:

ProfileController

final class ProfileController: UIViewController {
   
private var collectionView: UICollectionView?
    let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        layout.minimumLineSpacing = 1
        layout.minimumInteritemSpacing = 1
        layout.sectionInset = UIEdgeInsets(top: 0, left: 1, bottom: 0, right: 1)
        let size = (view.width - 4)/3
        layout.itemSize = CGSize(width: size, height: size)
        collectionView = UICollectionView(frame: .zero,
                                          collectionViewLayout: layout)
        // Headers
        collectionView?.register(ProfileInfoHeader.self,
                                 forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
                                 withReuseIdentifier: ProfileInfoHeader.identifier)
        
        collectionView?.register(MyTasksCollectionCell.self,
                                 forCellWithReuseIdentifier: MyTasksCollectionCell.identifier)
        
        collectionView?.delegate = self
        collectionView?.dataSource = self
        guard let collectionView = collectionView else {
            return
     }
        view.addSubview(collectionView)
    }
extension ProfileController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1 
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1 
    }
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyTasksCollectionCell.identifier,
                                                      for: indexPath)as! MyTasksCollectionCell
        
            return cell
        
    }

MyTaskCollectionCell

class MyTasksCollectionCell: UICollectionViewCell, UITableViewDelegate, UITableViewDataSource {

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                 tableView.deselectRow(at: indexPath, animated: true)
 let task = {() -> Add in
        switch (displayedTask) {
          case .current:
             // First segment tapped
            return self.tasks[indexPath.row]
          case past:
             // Second segment tapped
            return self.pastTasks[indexPath.row]
        }
    }()
     let vc = MyTasksDetailController() //ERROR HERE: Missing argument for parameter 'coder' in call : Insert 'coder: <#NSCoder#>'
self.present(vc, animated: true, completion: nil)

}

MyTaskTableCell

class MyPostsTableCell: UITableViewCell {
    
    var setdescriptionTitleLabel: String? {
        didSet {
            descriptionTitleLabel.text = setdescriptionTitleLabel ?? ""
        }
    }
    var setdateLabel: String? {
        didSet {
            dateLabel.text = setdateLabel ?? ""
        }
    }
    var sethourLabel: String? {
        didSet {
            hourLabel.text = sethourLabel ?? ""
        }
    }
    var setDateIcon: UIImage? {
        didSet {
            dateIcon.image = UIImage()
        }
    }
    var setHourIcon: UIImage? {
        didSet {
            hourIcon.image = UIImage()
        }
    }

MyTasksDetailController

class MyTasksDetailController: UIViewController  {

internal var task: Add? {
       didSet {
            if let task = task {
                setDescriptionLabel = task.description
                setDescriptionTitleLabel = task.descriptionTitle
             }
        }
    }    
    var setDescriptionLabel: String? {
        didSet {
            descriptionLabel.text = setDescriptionLabel ?? ""
        }
    }
    var setdescriptionTitleLabel: String? {
        didSet {
            descriptionTitleLabel.text = setdescriptionTitleLabel ?? ""
        }
    }
     let descriptionLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont.systemFont(ofSize: 28, weight: .bold)
        label.textAlignment = .center
        return label
    }()
    
     let descriptionTitleLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont.systemFont(ofSize: 18, weight: .bold)
        label.textAlignment = .center
        label.numberOfLines = 3
        return label
    }()
   let container: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.clipsToBounds = true
        v.backgroundColor = .white
        v.layer.cornerRadius = 24

        v.backgroundColor =
            // 1
            UIColor { traitCollection in
              // 2
              switch traitCollection.userInterfaceStyle {
              case .dark:
                // 3
                 v.layer.borderColor = UIColor.label.cgColor
                return UIColor.systemBackground

              default:
                // 4
                 v.layer.borderColor = UIColor.black.cgColor
                return UIColor.systemBackground
              }
            }
        return v
    }()
 lazy var stackContainer: UIStackView = {
       let stackContainer = UIStackView(arrangedSubviews: [stackDesLabel, stackDesTitLabel])
        stackContainer.translatesAutoresizingMaskIntoConstraints = false
        stackContainer.axis = .vertical
        stackContainer.distribution  = UIStackView.Distribution.fillEqually
       return stackContainer
   }()
    lazy var stackDesLabel: UIStackView = {
        let stackDesLabel = UIStackView(arrangedSubviews: [descriptionLabel])
        stackDesLabel.translatesAutoresizingMaskIntoConstraints = false
        stackDesLabel.axis = .vertical
        stackDesLabel.distribution  = UIStackView.Distribution.fillProportionally
        return stackDesLabel
    }()
    lazy var stackDesTitLabel: UIStackView = {
       let stackDesTitLabel = UIStackView(arrangedSubviews: [descriptionTitleLabel])
        stackDesTitLabel.translatesAutoresizingMaskIntoConstraints = false
        stackDesTitLabel.axis = .horizontal
        stackDesTitLabel.distribution  = UIStackView.Distribution.fillEqually
       return stackDesTitLabel
   }()
    override func viewDidLoad() {
        view.addSubview(stackDesLabel)
        view.addSubview(stackDesTitLabel)

        stackContainer.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true
        stackContainer.trailingAnchor.constraint(equalTo: container.trailingAnchor).isActive = true
        stackContainer.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
        stackContainer.centerXAnchor.constraint(equalTo: container.centerXAnchor).isActive = true
        stackContainer.heightAnchor.constraint(equalTo: container.heightAnchor).isActive = true
        stackContainer.widthAnchor.constraint(equalTo: container.widthAnchor).isActive = true
        
        stackDesTitLabel.topAnchor.constraint(equalTo: stackContainer.topAnchor, constant: 50).isActive = true
         stackDesTitLabel.widthAnchor.constraint(equalTo: stackContainer.widthAnchor).isActive = true
        stackDesTitLabel.centerXAnchor.constraint(equalTo: stackContainer.centerXAnchor).isActive = true
        stackDesLabel.topAnchor.constraint(equalTo: stackDesTitLabel.bottomAnchor, constant: 50).isActive = true
        stackDesLabel.leadingAnchor.constraint(equalTo: stackContainer.leadingAnchor, constant: 5).isActive = true
        stackDesLabel.widthAnchor.constraint(equalTo: stackContainer.widthAnchor).isActive = true
 }

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

添加(数据结构)

struct Add {
    static var details: Add = Add()
    var descriptionTitle: String = ""
    var description: String = ""
    var id: String?
    var date: String = ""
    var hour: String = ""

    func getDict() -> [String: Any] {
              let dict = [
                          "descriptionTitle": self.descriptionTitle,
                          "description": self.description,
                          "date": self.date,
                          "hour": self.hour,
                ] as [String : Any]
               return dict
         }

}

【问题讨论】:

  • 你确定这是你所有的代码吗?我觉得你的MyTasksDetailController 不完整,你可能有一些我们看不到的自定义init
  • 嘿,这不是我删除了很多以便更清楚,我在TasksDetailController中添加了更多内容

标签: swift inheritance uiviewcontroller initialization


【解决方案1】:

正如我所怀疑的,问题出在MyTasksDetailController 与您的实施

required init?(coder aDecoder: NSCoder)

如果您只是想要一个快速的解决方案,您可以根据对您的应用程序最有意义的方式执行以下两项操作之一:

  1. 删除required init?(coder aDecoder: NSCoder)
  2. 像这样添加您自己的初始化程序:
    init() {
        // Keep nil if you are not initializing from XIB
        super.init(nibName: nil, bundle: nil)
    }
    

说明

您尝试实现的目标违反了初始化继承规则,我相信这就是您收到该错误的原因。

我正在查看所有rules from here

当你这样做时:class MyTasksDetailController: UIViewController - 如果你遵循这些规则,你会自动继承 UIViewController 的初始化器:

自动初始化器继承

规则 1

如果你的子类没有定义任何指定的初始化器,它 自动继承其所有超类指定的初始化器。

规则 2

如果你的子类提供了它所有的实现 超类指定的初始化器——或者通过继承它们 规则 1,或者通过提供自定义实现作为其一部分 定义——然后它会自动继承所有的超类 便利初始化器。

即使您的子类添加了这些规则也适用 更多便利初始化器。

所以现在当你添加时:

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

它违反了规则 1,您正在添加自己的指定初始化程序,因此您丢失了之前继承的所有其他初始化程序,因此您收到此错误:

所以现在您有 2 个选项,如前所述。

1.删除required init?(coder aDecoder: NSCoder)

如果您在情节提要中创建视图控制器,则需要此版本的 init,因为在这种情况下会自动调用它。如果您不打算这样做,则可以将其删除。如果您打算在情节提要中使用它,则需要完成它:

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

2。添加你自己指定的初始化器

通过添加required init?(coder aDecoder: NSCoder),您丢失了之前继承的默认初始化程序,因此现在您需要自己创建:

init() {
    // Initialize your local vars
    
    // Call designated initializer from the super class
    // Keep nil if you are not initializing from XIB
    super.init(nibName: nil, bundle: nil)
}

这些都可以解决您的问题:

更新最后的想法

  1. 以上内容应该可以解决初始化错误
  2. 但是,您将在下一行出现错误self.present(vc, animated: true, completion: nil)

简而言之,present (documentation reference) 只能被视图控制器调用。

在您的代码中,MyTasksCollectionCell 是一个 UICollectionViewCell,因此您需要通知视图控制器您的集合视图所在的单元格已被点击,并且视图控制器需要处理呈现新视图。

您可以通过两种方式做到这一点:

  1. Delegates - 让视图控制器负责处理单元格点击并呈现另一个视图控制器
  2. Observers - 通知您的视图控制器处理单元格点击并呈现另一个视图控制器

这两个都会

这些只是给你一个想法的快速链接,但我建议你多用谷歌搜索一下,看看哪个最适合你的情况

【讨论】:

  • 谢谢你的解释,你是对的,MyTasksDetailController 之前是一个 UIView,我保留了相同的代码 --' 错误消失了,但现在有另一个错误:/ 这里说@987654342 @ 'MyTasksCollectionCell' 类型的值没有成员'present'。我猜是因为 MyTasksCollectionCell 不是 ViewController 但我不知道如何从 CollectionViewCell 推送/呈现视图:/
  • @dohoudjann - 我在答案末尾添加了一些更新来解释这一点。
  • 谢谢,我会调查的
  • 好的,我通过在我的 ProfileController cell.viewController = self 和类 MyTasksCollectionCell weak var viewController: UIViewController? 最后在 CollectionViewCell 内的 didSelectRowAt let vc = MyTasksDetailController() vc.task = task viewController?.present(vc, animated: true, completion: nil) 再次感谢您对代表的回答帮助我发现了关闭。
  • 很高兴听到@dohoudjann
猜你喜欢
  • 2019-11-25
  • 2016-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-01
  • 2017-04-25
  • 1970-01-01
相关资源
最近更新 更多