我正在开发一个测验应用程序,并且在初始视图控制器之后会出现第二个视图控制器,在该控制器中要求您回答问题。在第二个视图控制器上,用户必须按一个按钮才能返回到初始视图控制器,才能被问到另一个问题。然而,当我从第二个视图控制器回来时,我相信正在创建初始视图控制器的新实例,并且向用户询问他们已经回答的问题。我的初始视图控制器的swift文件中的代码构造成,一旦用户被问到一个问题,那么该问题就会被它的索引从数组中删除。我怎样才能将它从第二个视图控制器的segue中创建到初始视图控制器的新实例?或者有没有办法让第二个视图控制器可以访问与初始视图控制器相同的方法?
这是我的初始视图控制器的代码:
<?php
hi
?>
这是第二个视图控制器的代码:
import UIKit
class ViewController: UIViewController {
var questionList = [String]()
func updateCounter() {
counter -= 1
questionTimer.text = String(counter)
if counter == 0 {
timer.invalidate()
wrongSeg()
counter = 15
}
}
func randomQuestion() {
//random question
if questionList.isEmpty {
questionList = Array(QADictionary.keys)
questionTimer.text = String(counter)
}
let rand = Int(arc4random_uniform(UInt32(questionList.count)))
questionLabel.text = questionList[rand]
//matching answer values to go with question keys
var choices = QADictionary[questionList[rand]]!
questionList.remove(at: rand)
//create button
var button:UIButton = UIButton()
//variables
var x = 1
rightAnswerBox = arc4random_uniform(4)+1
for index in 1...4
{
button = view.viewWithTag(index) as! UIButton
if (index == Int(rightAnswerBox))
{
button.setTitle(choices[0], for: .normal)
}
else {
button.setTitle(choices[x], for: .normal)
x += 1
}
randomImage()
}
}
let QADictionary = ["Who is Thor's brother?" : ["Atum", "Loki", "Red Norvell", "Kevin Masterson"], "What is the name of Thor's hammer?" : ["Mjolinr", "Uru", "Stormbreaker", "Thundara"], "Who is the father of Thor?" : ["Odin", "Sif", "Heimdall", "Balder"]]
//wrong view segue
func wrongSeg() {
performSegue(withIdentifier: "incorrectSeg", sender: self)
}
//proceed screen
func rightSeg() {
performSegue(withIdentifier: "correctSeg", sender: self)
}
//variables
var rightAnswerBox:UInt32 = 0
var index = 0
//Question Label
@IBOutlet weak var questionLabel: UILabel!
//Answer Button
@IBAction func buttonAction(_ sender: AnyObject) {
if (sender.tag == Int(rightAnswerBox))
{
rightSeg()
print ("Correct!")
}
if counter != 0 {
counter = 15
questionTimer.text = String(counter)
}
else if (sender.tag != Int(rightAnswerBox)) {
wrongSeg()
print ("Wrong!")
timer.invalidate()
questionList = []
}
randomQuestion()
}
override func viewDidAppear(_ animated: Bool)
{
randomQuestion()
}
//variables
var counter = 15
var timer = Timer()
@IBOutlet weak var questionTimer: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
timer = Timer.scheduledTimer(timeInterval: 1, target:self, selector: #selector(ViewController.updateCounter), userInfo: nil, repeats: true)
}
答案 0 :(得分:1)
您需要什么,先生是代表或放松。我更喜欢代表,因为他们更容易理解,我认为更强大。
在ContinueScreen视图控制器中,定义类似于此的协议:
protocol QuizCompletedDelegate {
func completedQuiz()
func canceledQuiz()
}
同样在您的ContinueScreen视图控制器中,您需要声明QuizCompletedDelegate类型的可选委托
var delegate: QuizCompletedDelegate?
...并在适当的时候使用该委托调用函数:
@IBAction func didPressContinue(_ sender: Any) {
if allQuestionsAnswered == true {
delegate.completedQuiz()
} else {
delegate.cancelledQuiz()
}
}
在初始视图中,控制器是您实现协议功能的地方:
extension ViewController: QuizCompletedDelegate {
func completedQuiz() {
//Handle quiz complete
}
func cancelledQuiz() {
//Handle quiz cancelled
}
}
然后,您需要做的最后一件事是在初始视图控制器的prepareForSegue函数中设置ContinueScreen视图控制器的委托。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showContinueScreen" {
let continueVC = segue.destination as! ContinueScreen
continueVC.delegate = self
}
}
在初始视图控制器的ViewDidAppear上删除对randomQuestion()的调用,然后您就开始了!
答案 1 :(得分:1)
当你回去时,它不应该创建一个新的视图控制器。如果确实如此 - 它非常糟糕 - 您应该重新构建应用程序的流程...为了向前传递数据,我们应该使用依赖注入。要将数据传递给上一个视图控制器 - 请使用iOS委派模式。我建议花30-40分钟阅读(并理解这篇文章),这将使你今后更清楚:http://matteomanferdini.com/how-ios-view-controllers-communicate-with-each-other/。