在swift中调用webservice后,从异步调用函数返回数据并保存变量

时间:2016-08-23 15:59:47

标签: ios swift web-services variables task

我的代码有效,但无法保留变量返回的内容。 我只能打印但不能将它们存储在变量中。 我附上了用于webservice的类,因为我现在正在调用object。

class WebService{

    class func llamarWebService(completionHandler: (datos:NSArray)->()){

        let urlPath = "http://aaaaaaaaa.com.ar/aaaaaaaaa/forwarder_number?phone=0000000000"
        let url = NSURL(string: urlPath)
        let session = NSURLSession.sharedSession()
        var arreglo:NSArray!
        let task = session.dataTaskWithURL(url!,completionHandler: {data,response,error -> Void in

            if (error != nil){
                print(error?.localizedDescription)
            }

            let nsdata: NSData = NSData(data: data!)

            arreglo = self.retornarDatos(nsdata)
            completionHandler(datos: arreglo)


        })
        task.resume()
    }

    class func retornarDatos(nsdata: NSData)-> Array<String>{

        let datos = NSString(data:nsdata,encoding: NSUTF8StringEncoding)
        let partes = datos?.componentsSeparatedByString(",")
        var arreglo : [String] = []
        for i in partes!{
            arreglo.append(i)
        }

        return arreglo
    }

}

在视图控制器中使用此

 var resultadoWebService = WebService.llamarWebService{
    datos in print([datos[0],datos[1],datos[2],datos[3],datos[4]])
}

我需要保存例如:

var1 = datos[0]
var2 = datos[1]

实际上代码会在控制台中显示我

  

[好,LeoAndroid,20,2,2222222222]

1 个答案:

答案 0 :(得分:0)

首先,使用resultadoWebService没有意义。所以我会像这样简化你的代码片段:

WebService.llamarWebService { datos in
    print([datos[0],datos[1],datos[2],datos[3],datos[4]])
}

其次,您询问有关更新变量的问题。实际上,更新局部变量没有意义,但也许你想更新调用对象的属性。如果是这样,在闭包内更新它们,然后触发适合结果的任何UI更新(或其他):

var var1: String?
var var2: String?

func performRequestAndUpdateUI() {
    WebService.llamarWebService { datos in
        guard datos.count == 5 else {
            print("didn't get the number of items data I expected")
            return
        }

        guard datos[0] == "OK" else {
            print("not everything was OK")
            return
        }

        // note, you probably want to dispatch all model updates to the main queue
        // to simplify synchronization. also UI updates must happen on main queue,
        // too.

        dispatch_async(dispatch_get_main_queue()) {
            self.var1 = datos[1]
            self.var2 = datos[2]
            ...
            // do whatever UI updates you want here
        }
    }

    // but don't try to use `datos` results here, because the above runs 
    // asynchronously and we don't have the result by the time we get here 
    // in our code.
}

现在,datos是否总会有五个项目,以及您是否要检查datos[0]是否为OK取决于您,但希望它能说明这个想法,即你正在处理一个异步方法,所以你不能只是立即使用在闭包中传回的值,而是你必须将它们的使用限制在闭包本身。如果您要更新模型和/或UI,请确保将其分发回主线程。但是你无法立即更新变量,因为来自Web服务的响应是异步的,直到以后才会被调用。

我可能会建议稍微更安全(更简单)retornarDatos,它会删除!强制解包运算符,也许会使用可选链接,如下所示:

class func retornarDatos(data: NSData) -> [String]? {
    return String(data: data, encoding: NSUTF8StringEncoding)?
        .componentsSeparatedByString(",")
}

或者,如果确实想要在出现错误时返回一个空字符串数组,就像当前的再现一样,你可以这样做:

class func retornarDatos(data: NSData) -> [String] {
    return String(data: data, encoding: NSUTF8StringEncoding)?
        .componentsSeparatedByString(",") ?? [String]()
}

顺便说一下,我建议您聆听上述代码/概念,但一旦这样做,您可能需要重新评估您的Web服务设计。我建议考虑使用JSON作为响应,因为解析过程更加健壮,并且更容易区分基本Web服务错误和成功返回某些内容的Web服务(无论是否“OK”)。