线程 1:致命错误:init(coder:) 尚未实现
Posted
技术标签:
【中文标题】线程 1:致命错误:init(coder:) 尚未实现【英文标题】:Thread 1: Fatal error: init(coder:) has not been implemented 【发布时间】:2022-01-23 03:19:09 【问题描述】:我是 Xcode 和 Swift 的新手。
这是我的第一个程序。
我包含完整的代码。
我收到此错误,但不知道如何解决。
程序构建正常,但是当我运行它时出现此错误。
感谢您提供编码解决方案。
这是 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 及其下方的评论 【参考方案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)
,目前只是抛出一个致命错误。
您可以做以下三件事之一:
如 Joakim 所说,要么删除 required init?(coder: NSCoder)
和 init?(coder: NSCoder, responses: [Answer])
,然后使用 segue 实例化它
或者像这样删除init?(coder: NSCoder, responses: [Answer])
并正确实现required init?(coder: NSCoder)
:
required init?(coder: NSCoder)
self.responses = [Answer]()
super.init(coder: coder)
-
您也可以在声明时初始化
[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 而不更改程序中的任何内容,并且解决方案来了。
谢谢,感谢您提出的解决方案建议。
【讨论】:
以上是关于线程 1:致命错误:init(coder:) 尚未实现的主要内容,如果未能解决你的问题,请参考以下文章
UIViewController 和所需的初始化?(编码器:)
致命错误:尚未为模型“a”注册架构。使用 mongoose.model(name, schema)
Swift init 方法错误:声明 'init(coder:)' 不能覆盖多个超类声明