How to pass data backwards to a view controller after passing forward?

ぐ巨炮叔叔 提交于 2019-12-12 23:46:51

问题


Im developing a quiz app and there is a second view controller that appears after the initial view controller where you are asked to answer a question. On the second view controller you the user must press a button to return to the initial view controller to be asked another question. However when I segue back from the second view controller I believe a new instance of the initial view controller is being created and the user is asked questions they have already answered. The code in the swift file for my initial view controller is constructed that when once a user is asked a question once that question is removed from an array by it's index. How could I make it to where a new instance of the initial view controller isn't created from segueing from the second view controller? Or is there a way the second view controller can access the same methods as the initial view controller?

Here is my code for the initial view controller:

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)


}

Here's the code to the second view controller:

import UIKit




 class ContinueScreen: UIViewController {




//correct answer label
@IBOutlet weak var correctLbl: UILabel!

//background photo
@IBOutlet weak var backgroundImage: UIImageView!

func backToQuiz() {

    if let nav = self.navigationController {
        nav.popViewController(animated: true)
        }
    else {

        self.dismiss(animated: true, completion: nil)
        }

    }

@IBAction func `continue`(_ sender: Any) {


    backToQuiz()
}

回答1:


What you need, sir is a delegate or an unwind segue. I far prefer delegates because they're easier to understand and I think a bit more powerful.

In your ContinueScreen view controller define a protocol similar to this:

protocol QuizCompletedDelegate {
    func completedQuiz()
    func canceledQuiz()
}

Also in your ContinueScreen view controller you need to declare an optional delegate of type QuizCompletedDelegate

var delegate: QuizCompletedDelegate?

... and use that delegate to call the functions when appropriate:

@IBAction func didPressContinue(_ sender: Any) {
    if allQuestionsAnswered == true {
        delegate.completedQuiz()
    } else {
        delegate.cancelledQuiz()
    }
}

In your initial view controller is where you implement the functions for the protocol:

extension ViewController: QuizCompletedDelegate {
    func completedQuiz() {
        //Handle quiz complete
    }
    func cancelledQuiz() {
        //Handle quiz cancelled
    }
}

Then the last thing you need to do is set the delegate of your ContinueScreen view controller in the prepareForSegue function of your initial view controller.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showContinueScreen" {
        let continueVC = segue.destination as! ContinueScreen
        continueVC.delegate = self
    }
}

Remove the call to randomQuestion() on your initial view controller's ViewDidAppear, and you're in business!




回答2:


It shouldn't create a new View Controller when you go back. If it does - it's very bad - and you should re-architect the flow of your app... To pass data forward, we should use Dependency Injection. To pass data to the previous view controller - use the iOS Delegation Pattern. I recommend to spend 30-40 mins to read (and understand this article), and it will make things more clear for you in the future: http://matteomanferdini.com/how-ios-view-controllers-communicate-with-each-other/.



来源:https://stackoverflow.com/questions/45311634/how-to-pass-data-backwards-to-a-view-controller-after-passing-forward

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!