Ios 如何在两个单独的视图控制器上跟踪阵列的元素?
我正在开发一个测验应用程序,在第一个Ios 如何在两个单独的视图控制器上跟踪阵列的元素?,ios,arrays,swift,delegates,viewcontroller,Ios,Arrays,Swift,Delegates,Viewcontroller,我正在开发一个测验应用程序,在第一个UIViewController中,用户被问到一个问题,并被给予四个按钮作为答案。如果他们得到正确答案,那么该元素将从要提问的问题数组中删除。但是,如果我实现了一个到另一个视图控制器的分段,当该分段返回到第一个视图控制器以询问另一个问题时,询问用户是否要继续,则阵列将重新填充用户已经回答的问题,即使这些问题应该被删除。当我切换到询问用户是否要继续的第二个viewcontroller的和时,如何确保问题数组中没有填充已回答的问题 这是我的密码: import U
UIViewController
中,用户被问到一个问题,并被给予四个按钮作为答案。如果他们得到正确答案,那么该元素将从要提问的问题数组中删除。但是,如果我实现了一个到另一个视图控制器的分段,当该分段返回到第一个视图控制器以询问另一个问题时,询问用户是否要继续,则阵列将重新填充用户已经回答的问题,即使这些问题应该被删除。当我切换到询问用户是否要继续的第二个viewcontroller的和时,如何确保问题数组中没有填充已回答的问题
这是我的密码:
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)
}
第二视图控制器的代码:
import UIKit
class ContinueScreen: UIViewController {
//correct answer label
@IBOutlet weak var correctLbl: UILabel!
//background photo
@IBOutlet weak var backgroundImage: UIImageView!
func backToQuiz() {
performSegue(withIdentifier: "continueSeg", sender: self)
}
@IBAction func `continue`(_ sender: Any) {
backToQuiz()
}
override func viewDidLoad() {
super.viewDidLoad()
}
为此,您需要实施委托。你可以找到更多的信息 你的问题与我有关
请检查一下。希望有帮助 问题在于,当您返回到
backtoquick()
中的第一个视图控制器时,调用performSegue
,然后
- 创建第一个视图控制器的新实例,然后
- 使用原始(未修改的)测验数据重新初始化它
func backToQuiz() {
if let nav = self.navigationController {
nav.popViewController(animated: true)
} else {
self.dismiss(animated: true, completion: nil)
}
}
返回到父视图控制器实例。我认为问题不在于视图控制器之间来回传输数据,而在于在
backtoquick
中创建父视图控制器的新实例。如何防止视图控制器的新实例?不,为什么要创建新实例。请注意,Swift数组中的值类型。因此,默认情况下,如果复制数组,将创建一个新实例,并将所有元素复制到该实例中。您将要做的任何更改都将在新副本上执行,并且不会传播到从中复制该副本的阵列。第二个视图控制器根本不使用该阵列,因此不会复制到任何位置。问题是在backtoquick
中创建了一个新的viewcontroller,而不是返回到第一个viewcontroller。没有创建新的viewcontroller。您可以在控制台中进行检查。问题出在你的逻辑中的某个地方。我能看到的一个地方是,你在为每一个错误的答案制造问题。并且它会在ViewDid上再次填充数组。我不知道它是否是有意的。使用一个对象来存储数据,并从相关的视图控制器中引用它的一个实例;此外,请确保continueSeg
是一个不同于常规segues的如何展开segues?您可以搜索信息;苹果有一个非常好的技术说明。基本上,展开序列返回到现有的视图控制器实例。因此,使用序列时,确保不创建视图控制器新实例的最佳方法是什么?方法是弹出视图控制器/关闭当前实例,如上所示,或者看看上面评论中@Paulw11提到的segue unwinding。谢谢你的真知灼见!真的很有帮助。。我实现了你的代码,但它并不完全符合我的目的,但我认为这是朝着正确方向迈出的一步。