在异步请求完成后选择表后运行segue

时间:2015-07-16 20:48:28

标签: ios json

我正在尝试运行url请求以在选择某个表行之后获取JSON文件,基于该行与URL请求一起发送唯一ID并生成不同的JSON。这是我的准备世界

    // MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
     // Get the new view controller using segue.destinationViewController.
    var divisionScene = segue.destinationViewController as! DivisionViewController

    // Pass the selected object to the new view controller.
    if let indexPath = tableView.indexPathForSelectedRow() {
    let arrayIndex = indexPath.row
       //println("Index: \(arrayIndex)")

        torneoIDTransfer = torneos[arrayIndex].torneoID
        //println("\(torneoIDTransfer)")


        //check second url with second request type same token
        //sets url to string using token
        let tercerURL = NSURL(string: "http://api.zione.mx/get.json.asp?tr=3&tkn=\(tkn)&tor=\(torneoIDTransfer)")

        //initializes request

        let request = NSURLRequest(URL: tercerURL!)
        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.currentQueue()) { response, jsonDataRequest3, error in
            let dataRequest3 = jsonDataRequest3

            //takes data, saves it as json
            let tercerJSON = JSON(data: jsonDataRequest3)

            //checks to see that contents != nil, meaning the JSON file was found
            if tercerJSON != nil {

                //checks amount of tournaments available in order to generate table.
                let divisionCount = tercerJSON["lista-divisiones"].count
                //sets global variable numero de torneos
                numeroDeDivisiones = divisionCount


                //for loop to go insert into Torneo nuevo each ID and name by using count from above
                for var index = 0; index < divisionCount; ++index {
                    var divisionID = Int(tercerJSON["lista-divisiones" ][index]["DivisionID"].number!)
                    var nomDivision = tercerJSON["lista-divisiones"][index]["nomDivision"].string
                    //println("\(divisionID)")
                    //println("\(nomDivision)")
                    var divisionNuevo = listaDivisiones(divisionID: divisionID, nomDivision: nomDivision!)
                    divisiones.append(divisionNuevo)
                    numeroDeDivisiones = 10
                    print("WHO IS FIRST")
                }
            }
            print("\(divisiones[0].nomDivision)")
        }
    }
}

我通过从表格单元格拖动到新视图控制器来创建我的赛格威。但是,当我单击表格单元格时,转换会在请求有机会完成之前立即发生转换,因此不会显示任何数据。

2 个答案:

答案 0 :(得分:1)

  
    

“在请求有机会完成之前,转换立即发生”。

  

当然它确实如此,这正是异步意味着什么。你提到它是异步的,你必须对这意味着什么有误解。解释您认为这意味着什么以及您对代码的期望,以便您可以更好地接受我们的教育。

当您调用sendAsynchronousRequest()时,请将您的程序视为分支为两个(实际上这实际上是有效的)。一部分是您的原始代码,它将继续执行,即您的prepareFoSegue代码将继续执行。 同时,并行地,OS将执行请求,并且当请求完成时,将传递您传递给sendAsynchronousRequest()的块中的代码。因此,您的prepareForSeque()函数将在收到Json之前完成。

但除此之外,你不应该试图或希望或者希望在segue过渡之前获取JSon - 这样做会停止你的ui。假设sendAsynchronousRequest()是sendSynchronousRequest()而且需要10秒才能完成,你认为应用程序在运行时会产生什么后果?

您应该在GUI准备好显示之前长时间获取数据,或者如果不可能,请立即显示没有数据的GUI,然后在数据到达时更新它。

答案 1 :(得分:1)

在用户选择表格行之前很久,在后台获取和处理数据是理想的。如果这是不可能的,那么我建议您让目标视图控制器执行URL请求。 URL请求是异步发生的,因此在取消分配源视图控制器之前,它永远不会有机会完成。

在源视图控制器中,修改prepareForSegue

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    var divisionScene = segue.destinationViewController as! DivisionViewController

    if let indexPath = tableView.indexPathForSelectedRow() {
        let arrayIndex = indexPath.row

        torneoIDTransfer = torneos[arrayIndex].torneoID

        let tercerURL = NSURL(string: "http://api.zione.mx/get.json.asp?tr=3&tkn=\(tkn)&tor=\(torneoIDTransfer)")

        divisionScene.fetchDataAtURL(tercerURL)
    }
}

您需要在目标视图控制器中定义一个方法来处理提取。

func fetchDataAtURL(URL: NSURL) {
    let request = NSURLRequest(URL: tercerURL!)
    NSURLConnection.sendAsynchronousRequest( // ... your fetching logic here
}

一旦数据到达,您还需要一些逻辑来显示数据。我建议将它放入你的请求的完成回调中(或者更确切地说,让回调触发显示更新)。如果您的divisionScene是tableView,则可以调用reloadData(更新数据源后)。如果没有,您将需要一些其他方式来更新UI。如果要更新UI,请确保dispatch到该部分的主队列。

这样做至少会将URL加载责任传递给目标视图控制器,这至少会在数据最终到达时为止。