Mikhail Sh. Mikhail Sh. - 1 month ago 12
iOS Question

Async task don't change external variable. Swift 3

I can't save data from URL, because function in infinit loop. How fix it?
My code:

func getRegion2(){
let method = "region/"

var url = serviceUrl+method
var myArray: [String]()
while(url != nil){

Alamofire.request(url).validate().responseJSON { response in
switch response.result {
case .success(let data):

let nextUrl = JSON(data)["next"].stringValue
url = nextUrl
myArray = myArray + myArray
print(nextUrl)

case .failure(let error):
print("Request failed with error: \(error)")
}
}
}
print(myArray)
}


If run without the "while", then everything works fine.

Answer

One possible solution is to combine a recursive function and a dispatch group (not tested):

func getRegion2(){
    let method = "region/"

    var url = serviceUrl+method
    var myArray: [String] = []

    let group = DispatchGroup()

    func getRegion(with url: String) {
        group.enter()
        Alamofire.request(url).validate().responseJSON { response in
            switch response.result {
            case .success(let data):

                let nextUrl = JSON(data)["next"].stringValue
                myArray = myArray + someArrayFromRespnse
                print(nextUrl)

                if nextUrl != nil {
                    getRegion(with: nextUrl)
                }

                group.leave()
            case .failure(let error):
                print("Request failed with error: \(error)")
            }
        }
    }

    getRegion(with: url)

    group.notify(queue: DispatchQueue.main) { 
        print(myArray)
    }
}

I would use a completionBlock:

func getRegion2(completion: () -> [String]?) {
    let method = "region/"
    var url = serviceUrl+method
    var myArray: [String] = []

    func getRegion(with url: String) {
        Alamofire.request(url).validate().responseJSON { response in
            switch response.result {
            case .success(let data):

                let nextUrl = JSON(data)["next"].stringValue
                myArray = myArray + someArrayFromRespnse
                print(nextUrl)

                if nextUrl != nil {
                    getRegion(with: nextUrl)
                } else {
                    completion(myArray)
                }

            case .failure(let error):
                completion(nil)
            }
        }
    }

    getRegion(with: url)
}
Comments