Search code examples
swiftclosuresalamofireswift3

Cannot change variable from a closure in the same class [swift 3.0]


var serviceTypeName = [String]()

override func viewDidLoad() {
    super.viewDidLoad()
    getServiceType()
    debugPrint(serviceTypeName)
}

I try to get an array of names from web API, and store it into the array serviceTypeName. Below is my function of get service name (I used Alamorfire lib)

func getServiceType() {
            Alamofire.request(...
                .responseJSON { response in
                    switch response.result {
                    case .success:

                        if let responseValue = response.result.value {
                            var serviceName: [String] = []
                            let json = JSON(responseValue)

                            for (key, subJson):(String, JSON) in json["results"] {

                                if let name = subJson["name"].string {
                                    serviceName.insert(name, at: Int(key)!)

                                }
                            }
                            self.serviceTypeName = serviceName

                        } ...

However, I got null array [] after this function, just like the function didn't do anything. I make sure that I got correct data from server and put into serviceName correctly every loop. But I cannot set it to the serviceTypeName. Would you please point out the mistakes?


Solution

  • I got null array [] after this function, just like the function didn't do anything.

    That's right, the function did not do anything. More precisely, the function did not do anything yet. Checking the value after the function is premature, because the callback is executed asynchronously, when the data arrives.

    You need to split your code into two parts:

    • The first part initiates the call, and gives it a callback that sets properties to the results received from the call
    • The second part processes the results, displaying the properties or doing whatever else you planned to do

    Once the callback is done setting the properties, it needs to initiate the call for the second part, which makes use of these properties.

    func getServiceType() { // Part 1
        ...
        self.serviceTypeName = serviceName
        dispatch_async(dispatch_get_main_queue()) {
            processServiceName()
        }
    
    }
    
    func processServiceName() { // Part 2
        ... // Do things with self.serviceTypeName
    }