2017-08-14 63 views
1

我試圖寫在斯威夫特完成處理功能,這是我在斯威夫特代碼名爲NBObjectiOS的斯威夫特3 CompletionHandler不工作

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: [:] 
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>"; 
}) 
] 

有一兩件事我注意到的是,控制檯將首先打印對象作爲空[:]和成功日誌,那麼JSON數據。

所以我肯定我的findObjectInBackground()函數有問題,我只是不知道問題出在哪裏。

任何幫助將不勝感激!

+1

你是什麼意思「它不能正確打印對象」?如果你的意思是'NSArray'部分,那是因爲你的字典類型是'[String:Any]',並且當你解析JSON對象時,你不會向下轉換爲任何顯式類型。 –

+0

是的,我的意思是對象:[:]部分,所以我應該在ViewController.swift調用的函數中做什麼? – cubycode

+0

所以問題不在於打印,而是完成處理程序爲空。看看我的答案。 –

回答

1

你必須把完成處理器數據任務的完成處理

可以省略URLRequest的創作,得到的是默認的,只是通過網址:

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 3這個關閉聲明就足夠了:

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

它像一個魅力,非常感謝! – cubycode

1

問題是您在網絡請求的完成處理程序之外調用完成處理程序,因此您的函數的完成處理程序在異步網絡請求返回之前會返回。您需要將其移動到請求的完成處理程序中。

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