WMueller
WMueller

Reputation: 61

Assign value to Class Member within Function

I have a class that has two member variables and a function. The function is called when the user navigates to a new storyboard and uses a http GET request with member variable y to assign a value to member variable x. After the function is finished, I try to assign x to the new storyboard's variable, however it is nil. How do I assign a value to x within the function and then pass x to the new storyboard?

import UIKit
import os.log

class testViewController: UIViewController {

    var x: XClass!
    var y = “1234”

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

    // MARK: - Navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)

        switch(segue.identifier ?? "") {
        case “ZViewController”:
            guard let zviewcontroller = segue.destination as? ZViewController else{
                fatalError("Unexpected Destination: \(segue.destination)")
            }

            loadXDetail()
            zviewcontroller.x = x


        default:
            os_log("Not ZViewController Segue", log: OSLog.default, type: .debug)
        }
    }

    private func loadX(){
        // credentials encoded in base64
        let username = “***”
        let password = “***”
        let loginData = String(format: "%@:%@", username, password).data(using: String.Encoding.utf8)!
        let base64LoginData = loginData.base64EncodedString()

        // create the request
        let url = URL(string: "https://example.com")!
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.setValue("Basic \(base64LoginData)", forHTTPHeaderField: "Authorization")

        //making the request
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                print("\(error)")
                return
            }

            if let httpStatus = response as? HTTPURLResponse {
                // check status code returned by the http server
                print("status code = \(httpStatus.statusCode)")
                do {
                    let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
                    let items = json["items"] as? [[String: Any]] ?? []
                    for dic in items{
                        //guard let api = dic["Type"] as? String else {return}
                        let a = dic[“A”] as! String
                        let b = dic[“B”] as! String
                        let c = dic[“C”] as! String

                        self.x = XClass(y: y, a: a, b: b, c: c)!
                    }
                } catch let error as NSError {
                    print(error)
                    return
                }
            }
        }
        task.resume()
    }
}

Upvotes: 0

Views: 87

Answers (2)

FRIDDAY
FRIDDAY

Reputation: 4159

swift 4.2 / Xcode 10.1:

There are few ways to pass data between viewControllers or classes.

The easiest one is using Global variable. For Example:

import UIKit

var myGlobalVariable = ""  //Or any Type you need

class testViewController: UIViewController {

private func loadX(){

//Do some stuff ...

myGlobalVariable = x

}

import UIKit

class ZViewController: UIViewController {

override func viewDidLoad() {

print(myGlobalVariable)

}

Or, using singleton pattern. For Example:

Create a class like:

import Foundation

class  SetVariable {

    var test: String?  //Or any type you need

    private init () {}

    static let shared = SetVariable.init()
}

class testViewController: UIViewController {

private func loadX(){

//Do some stuff ...

SetVariable.shared.test = x

}

class ZViewController: UIViewController {

override func viewDidLoad() {

print(SetVariable.shared.test)

}

Upvotes: 1

Shehata Gamal
Shehata Gamal

Reputation: 100503

You can't prevent a segue inside prepare(for segue until your request finishes , you need to start the call to the asynchonous method when you need to navigate

loadX()

then inside the completion of let task = URLSession.shared.dataTask(with: request) do

 self.x = XClass(y: y, a: a, b: b, c: c)!
 }
 DispatchQueue.main.async {
    self.performSegue(withIdentifier:"SegueID",sender:nil)
 }

and at that moment the x var has a correct value according to the response


another thing you may need x as any array as it will contain the last value from this loop

                for dic in items{
                    //guard let api = dic["Type"] as? String else {return}
                    let a = dic[“A”] as! String
                    let b = dic[“B”] as! String
                    let c = dic[“C”] as! String

                    self.x = XClass(y: y, a: a, b: b, c: c)!
                }

plus consider using Codable to decode your response instead of JSONSerialization

Upvotes: 1

Related Questions