iOS Swift 3 CompletionHandler无法正常工作

时间:2017-08-14 15:08:29

标签: json swift3 completionhandler

我正在尝试在Swift中编写一个完成处理函数,这是我在Swift中使用一个名为NBObject的类的代码

typealias CompletionHandler = (_ success: Bool, _ data: [String:Any]) -> Void

// FIND OBJECTS IN BACKGROUND
func findObjectInBackground(completionHandler: CompletionHandler) {
    let tbNameStr = "table=" + theTableName
    var rStr = ""
    var theData = [String:Any]()

    for i in 0..<columns.count {
        rStr += "&c" + "\(i)" + "=" + columns[i] +
            "&r" + "\(i)" + "=" + records[i]
    }
    recordString = tbNameStr + rStr
    print("RECORD STRING: \(recordString)")

    let requestURL = URL(string: PATH_TO_API_FOLDER + "queryWhereKeyContains.php?" + recordString)

    //create the session object
    let session = URLSession.shared

    //now create the URLRequest object using the url object
    let request = URLRequest(url: requestURL!)

    //create dataTask using the session object to send data to the server
    let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in

        //exiting if there is some error
        if error != nil {
            print("Error is: \(error!.localizedDescription)")
            return
        } else {

        }

        do {
            if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any] {
                theData = json
                print("JSON: \(json)")
            }
        } catch let error { print("ERROR IN PARSING JSON: \(error.localizedDescription)") }

    })

    task.resume()


    let flag = true
    completionHandler(flag, theData)
}

我在我的ViewController.swift中调用该函数,如下所示:

let query = NJObject(tableName: HOTEL_TABLE_NAME)
query.whereKeyContains(columnName: HOTEL_NAME, record: "Hotel")
query.findObjectInBackground { (succ, objects) in
    print("OBJECTS: \(objects)")
    print("SUCCESS: \(succ)")
}

因此,在Xcode控制台中,我正确地获取了我的JSON数据,但在打印完成处理程序时,data(打印为OBJECTS)为空。

OBJECTS: [:]
SUCCESS: true
JSON: ["objects": <__NSArrayM 0x17004b4c0>(
{
    address = "<null>";
    createdAt = "2017-08-12 23:08:48";
    description = "lorem ipsec dolor sit";
    email = "<null>";
},
{
    address = "<null>";
    createdAt = "2017-08-14 06:19:10";
    description = "lorem ipsec dolor sit";
    email = "<null>";
})
]

我注意到的一件事是控制台首先打印OBJECTS并清空[:]和SUCCESS日志,然后是JSON数据。

所以我确信我的findObjectInBackground()函数有问题,我无法弄清楚问题出在哪里。

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

问题是您在网络请求的完成处理程序之外调用完成处理程序,因此函数的完成处理程序在异步网络请求返回之前返回。您需要在请求的完成处理程序中移动它。

do {
    if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any] {
        theData = json
        print("JSON: \(json)")
        completionHandler(true, theData)
    }
}

答案 1 :(得分:1)

您必须将完成处理程序放入数据任务的完成处理程序

您可以省略URLRequest的创建,GET是默认设置,只需传递网址:

let task = session.dataTask(with: requestURL!, completionHandler: { data, response, error in

    //exiting if there is some error
    if error != nil {
        print("Error is: \(error!.localizedDescription)")
        completionHandler(false, [:])
        return
    } 

    do {
        if let json = try JSONSerialization.jsonObject(with: data!) as? [String: Any] {
            print("JSON: \(json)")
            completionHandler(true, json) // the variable `theData` is not needed.
        }
    } catch let error { print("ERROR IN PARSING JSON: \(error.localizedDescription)") }
      completionHandler(false, [:])
})

task.resume()

不要通过.mutableContainers,它在Swift

中毫无意义

旁注:在Swift 3中,这个闭包声明就足够了:

typealias CompletionHandler = (Bool, [String:Any]) -> Void