【问题标题】:Thread 1: Fatal error: init(coder:) has not been implemented线程 1:致命错误:init(coder:) 尚未实现
【发布时间】:2022-01-23 03:19:09
【问题描述】:

我是 Xcode 和 Swift 的新手。

这是我的第一个程序。

我包含完整的代码。

我收到此错误,但不知道如何解决。

程序构建正常,但是当我运行它时出现此错误。

线程 1:致命错误:init(coder:) 尚未实现

感谢您提供编码解决方案。

这是 ResultView Controller.swift 文件。

//
//  ResultsViewController.swift
//  PersonalityQuiz
//
//  Created by Ricardo E. Marrero Guzmán on 12/16/21.
//

import UIKit

class ResultsViewController: UIViewController {

    @IBOutlet var resultAnswerLabel: UILabel!
    @IBOutlet var resultDefinitionLabel: UILabel!
    
    var responses: [Answer]  // Esto provoca un error.  Para quitarlo se añade el siguiente init?...
    
    init?(coder: NSCoder, responses: [Answer]) {  // Este init?... provoca otro error.  Se le da fix y se crea el siguiente required init?...
        self.responses = responses
        super.init(coder: coder)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented") // Thread 1: Fatal error: init(coder:) has not been implemented
    }

override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        
        calculatePersonalityResults()
        navigationItem.hidesBackButton = true
    }
    
    func calculatePersonalityResults() {
        
        let frecuencyOfAnswers = responses.reduce(into: [:]) {
            (counts, answer) in counts[answer.type, default: 0] += 1
        }
let frequentAnswersStored = frecuencyOfAnswers.sorted(by:
        { (pair1, pair2) in
            return pair1.value > pair2.value
        })
        
        let mostCommonAnswer = frequentAnswersStored.first!.key
        
        resultAnswerLabel.text = "You are \(mostCommonAnswer.rawValue)!"
        resultDefinitionLabel.text = mostCommonAnswer.definition

}

这是 de QuestionViewController.swift 文件

//
//  QuestionViewController.swift
//  PersonalityQuiz
//
//  Created by Ricardo E. Marrero Guzmán on 12/16/21.
//

import UIKit

class QuestionViewController: UIViewController {
    
    @IBOutlet var questionLabel: UILabel!
    
    @IBOutlet var singleStackView: UIStackView!
    @IBOutlet var singleButton1: UIButton!
    @IBOutlet var singleButton2: UIButton!
    @IBOutlet var singleButton3: UIButton!
    @IBOutlet var singleButton4: UIButton!
    
    @IBOutlet var multipleStackView: UIStackView!
    @IBOutlet var multiLabel1: UILabel!
    @IBOutlet var multiLabel2: UILabel!
    @IBOutlet var multiLabel3: UILabel!
    @IBOutlet var multiLabel4: UILabel!
    
    @IBOutlet var multiSwitch1: UISwitch!
    @IBOutlet var multiSwitch2: UISwitch!
    @IBOutlet var multiSwitch3: UISwitch!
    @IBOutlet var multiSwitch4: UISwitch!
    
    @IBOutlet var rangedStackView: UIStackView!
    @IBOutlet var rangedLabel1: UILabel!
    @IBOutlet var rangedLabel2: UILabel!
    
    @IBOutlet var rangedSlider: UISlider!
    
    @IBOutlet var questionProgressView: UIProgressView!

var answersChosen: [Answer] = [] // No se donde va esto
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        
        updateUI()
        
    }
    
    @IBAction func singleAnswerButtonPressed(_ sender: UIButton) {
        let currentAnswers = questions[questionIndex].answers
        
        switch sender {
        case singleButton1:
            answersChosen.append(currentAnswers[0])
        case singleButton2:
            answersChosen.append(currentAnswers[1])
        case singleButton3:
            answersChosen.append(currentAnswers[2])
        case singleButton4:
            answersChosen.append(currentAnswers[3])
        default:
            break
        }
        
        nextQuestion()
    }
    
    @IBAction func multipleAnswerButtonPressed() {
        let currentAnswers = questions[questionIndex].answers
        
        if multiSwitch1.isOn {
            answersChosen.append(currentAnswers[0])
        }
        if multiSwitch2.isOn {
            answersChosen.append(currentAnswers[1])
        }
        if multiSwitch3.isOn {
            answersChosen.append(currentAnswers[2])
        }
        if multiSwitch4.isOn {
            answersChosen.append(currentAnswers[3])
        }
        
        nextQuestion()
    }
    
    @IBAction func rangedAnswerButtonPressed() {
        let currentAnswers = questions[questionIndex].answers
        
        let index = Int(round(rangedSlider.value * Float(currentAnswers.count - 1)))
        
        answersChosen.append(currentAnswers[index])
        
        nextQuestion()
    }
    
    func updateUI() {
        singleStackView.isHidden = true
        multipleStackView.isHidden = true
        rangedStackView.isHidden = true
        
        let currentQuestion = questions[questionIndex]
        let currentAnswers = currentQuestion.answers
        let totalProgress = Float(questionIndex) / Float(questions.count)
        
        navigationItem.title = "Question #\(questionIndex + 1)"
        questionLabel.text = currentQuestion.text
        questionProgressView.setProgress(totalProgress, animated: true)
        
        switch currentQuestion.type {
        case .single:
            singleStackView.isHidden = false
            updateSingleStack(using: currentAnswers)
        case .multiple:
            multipleStackView.isHidden = false
            updateMultipleStack(using: currentAnswers)
        case .ranged:
            rangedStackView.isHidden = false
            updateRangedStack(using: currentAnswers)
        }
    }
    
    func updateSingleStack(using answers: [Answer]) {
        singleStackView.isHidden = false
        singleButton1.setTitle(answers[0].text, for: .normal)
        singleButton2.setTitle(answers[1].text, for: .normal)
        singleButton3.setTitle(answers[2].text, for: .normal)
        singleButton4.setTitle(answers[3].text, for: .normal)
    }
    
    func updateMultipleStack(using answers: [Answer]) {
        multipleStackView.isHidden = false
        
        multiSwitch1.isOn = false
        multiSwitch2.isOn = false
        multiSwitch3.isOn = false
        multiSwitch4.isOn = false
        
        multiLabel1.text = answers[0].text
        multiLabel2.text = answers[1].text
        multiLabel3.text = answers[2].text
        multiLabel4.text = answers[3].text
    }
    
    func updateRangedStack(using answers: [Answer]) {
        rangedStackView.isHidden = false
        
        rangedSlider.setValue(0.5, animated: false)
        
        rangedLabel1.text = answers.first?.text
        rangedLabel2.text = answers.last?.text
    }
    
    func nextQuestion() { // Este es el método más importante del programa y lo que hace correr el app bien.
        questionIndex += 1
        
        if questionIndex < questions.count {
            updateUI()
        } else {
            performSegue(withIdentifier: "Results", sender: nil)
        }
    }

    @IBSegueAction func showResults(_ coder: NSCoder) -> ResultsViewController? {
        return ResultsViewController(coder: coder, responses: answersChosen)
    }

这是 Question.swift 文件。

//
//  Question.swift
//  PersonalityQuiz
//
//  Created by Ricardo E. Marrero Guzmán on 12/17/21.
//

import Foundation

struct Question {
    var text: String
    var type: ResponseType
    var answers: [Answer]
}

enum ResponseType {
    case single, multiple, ranged
}

struct Answer {
    var text: String
    var type: AnimalType
}

enum AnimalType: Character {
    case dog = "????", cat = "????", rabbit = "????", turtle = "????"
    
    var definition: String {
        switch self {
        case .dog:
            return "You are incredibly outgoing.  You sorround yourself with the people you love and enjoy activities with your friends."
        case .cat:
            return "Mischievous, yet mild-tempered, you enjoy doing things on your own terms."
        case .rabbit:
            return "You love everithings that's soft.  You are healthy and full of energy."
        case .turtle:
            return "You are wise beyond your years, and you focus on the details.  Slow and steady wins the race."
        }
    }
}

var questions: [Question] = [
    Question(
        text: "Which food do you like the most?",
        type: .single,
        answers: [
            Answer(text: "Steak", type: .dog),
            Answer(text: "Fish", type: .cat),
            Answer(text: "Carrots", type: .rabbit),
            Answer(text: "Corn", type: .turtle)
        ]
    ),
    
    Question(
        text: "Which activities do you enjoy?",
        type: .multiple,
        answers: [
            Answer(text: "Swimming", type: .turtle),
            Answer(text: "Sleeping", type: .cat),
            Answer(text: "Cuddling", type: .rabbit),
            Answer(text: "Eating", type: .dog)
        ]
    ),
    
    Question(
        text: "How much do you enjoy car rides?",
        type: .ranged,
        answers: [
            Answer(text: "I dislike them", type: .cat),
            Answer(text: "I get a little nervous", type: .rabbit),
            Answer(text: "I barely notice them", type: .turtle),
            Answer(text: "I love them", type: .dog)
        ]
    )
]

var questionIndex = 0

这是介绍ViewController的文件。

//
//  ViewController.swift
//  PersonalityQuiz
//
//  Created by Ricardo E. Marrero Guzmán on 12/16/21.
//

import UIKit

class IntroductionViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func unwindToQuizIntroduction(segue: UIStoryboardSegue) {
        
    }

}

【问题讨论】:

  • 如果您使用情节提要,您的自定义 init 将不会被调用,因此您可以删除它和另一个调用 fatalError 的 init。而是使用 prepare for segue 来设置您的 Answer 数组。
  • 查看here 及其下方的评论

标签: swift


【解决方案1】:

看起来你错误地实例化了你的视图控制器 您没有共享足够的代码,但我可以假设您忘记从 xib 加载 Xcode 试试这个:

let storyboard = UIStoryboard(name: "myStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "myVCIdentifier")
present(vc, animated: true)

【讨论】:

    【解决方案2】:

    当 UIViewController 从 Storyboard 实例化时,它会调用 required init?(coder: NSCoder),目前只是抛出一个致命错误。 您可以做以下三件事之一:

    1. 如 Joakim 所说,要么删除 required init?(coder: NSCoder)init?(coder: NSCoder, responses: [Answer]),然后使用 segue 实例化它

    2. 或者像这样删除init?(coder: NSCoder, responses: [Answer])并正确实现required init?(coder: NSCoder)

    required init?(coder: NSCoder) {
        self.responses = [Answer]()
        super.init(coder: coder)
    }
    
    1. 您也可以在声明时初始化[Answer],这样就不需要required init?(coder: NSCoder),并且可以删除两个init,就像选项1一样:
     var responses = [Answer]()
    

    【讨论】:

      【解决方案3】:

      您需要在您的QuestionViewController 中实现prepare(for: segue) 并使用此函数来传递您的Answer 数组

      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
          if (segue.identifier == "Results") {
              let viewController = segue.destination as? MyOrderDetailsVC
              viewController!.responses = answersChosen
          }
      }
      

      【讨论】:

        【解决方案4】:

        终于找到了解决办法。问题是丢失的 segue 连接。我重新连接 segue 而不更改程序中的任何内容,并且解决方案来了。

        谢谢,感谢您提出的解决方案建议。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-17
          • 1970-01-01
          • 2014-07-25
          • 2016-12-22
          • 1970-01-01
          相关资源
          最近更新 更多