0

i have a problem while I'm initializing object of some class. What is wrong with that? (I can upload all my code but it is large if needed)enter image description here

Edit: My view controller code:

    import UIKit

class ViewController: UIViewController{

@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var answerStackView: UIStackView!

// Feedback screen
@IBOutlet weak var resultView: UIView!
@IBOutlet weak var dimView: UIView!
@IBOutlet weak var resultLabel: UILabel!
@IBOutlet weak var feedbackLabel: UILabel!
@IBOutlet weak var resultButton: UIButton!

@IBOutlet weak var resultViewBottomConstraint: NSLayoutConstraint!
@IBOutlet weak var resultViewTopConstraint: NSLayoutConstraint!

var currentQuestion:Question?

let model = QuizModel()
var questions = [Question]()

var numberCorrect = 0

override func viewDidLoad() {
    super.viewDidLoad()
    model.getQuestions()
}

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nil, bundle: nil)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


func setAll(questionsReturned:[Question]) {
    /*
    // Do any additional setup after loading the view, typically from a nib.

    // Hide feedback screen
    dimView.alpha = 0

    // Call get questions
    questions = questionsReturned

    // Check if there are questions
    if questions.count > 0 {

        currentQuestion = questions[0]

        // Load state
        loadState()

        // Display the current question
        displayCurrentQuestion()
    }
*/
print("Called!")

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

My QuizModel code:

 import UIKit
 import FirebaseDatabase


class QuizModel: NSObject {

override init() {
    super.init()
}

var ref:FIRDatabaseReference?
var test = [[String:Any]]()
var questions = [Question]()
weak var prot:UIPageViewControllerDelegate?
var first = ViewController()

func getQuestions(){
  getRemoteJsonFile()
}


func pars(){


    /*let array = test
    var questions = [Question]()

    // Parse dictionaries into Question objects
    for dict in array {

        // Create question object
        let q = Question()

        // Assign question properties
        q.questionText = dict["question"] as! String
        q.answers = dict["answers"] as! [String]
        q.correctAnswerIndex = dict["correctIndex"] as! Int
        q.module = dict["module"] as! Int
        q.lesson = dict["lesson"] as! Int
        q.feedback = dict["feedback"] as! String

        // Add the question object into the array
        questions += [q]
    }
    */

    //Protocol setAll function
    first.setAll(questionsReturned: questions)
}

func getRemoteJsonFile(){

    ref = FIRDatabase.database().reference()

    ref?.child("Quiz").observeSingleEvent(of: .value, with: { (snapchot) in

        print("hey")
        let value = snapchot.value as? [[String:Any]]
        if let dict = value {
            self.test = dict
            self.pars()
        }
    })
}

This isn't my all code but I think that is the most important part. In QuizModel code I'm reskining my code from getting json file to get data from firebase so you can see names of functions like 'getRemoteJSONFile' and in parse function parsing json but it isn't an issue of my problem I think

Jacob233
  • 312
  • 2
  • 4
  • 14

2 Answers2

2

It looks like you're trying to initialize a constant before you've initialized the viewController it lives in. Your have to make it a var and initialize it in viewDidLoad (or another lifecycle method), or make it a lazy var and initialize it at the time that it's first accessed.

creeperspeak
  • 5,403
  • 1
  • 17
  • 38
2

The problem boils down to the following:

class ViewController ... {
   let model = QuizModel()
}

class QuizModel ... {
   var first = ViewController()
}

The variable initializers are called during object initialization. When you create an instance of ViewController, an instance of QuizModel is created but its initialization creates a ViewController which again creates a new QuizModel and so on.

This infinite cycle will sooner or later crash your application (a so called "stack overflow").

There is probably some mistake on your side. Maybe you want to pass the initial controller to QuizModel, e.g.?

class ViewController ... {
    lazy var model: QuizModel = {
       return QuizModel(viewController: self)
    }
}

class QuizModel ... {
     weak var viewController: ViewController?

     override init(viewController: ViewController) {
        self.viewController = viewController
     }
}

Also make sure you are not creating ownership cycles (that's why I have used weak).

In general it's a good idea to strictly separate your model classes and your UI classes. You shouldn't pass view controllers (or page view controller delegate) to your model class. If you need to communicate with your controller, create a dedicated delegate for that.

Sulthan
  • 128,090
  • 22
  • 218
  • 270