iOS Swift 3 CompletionHandler 不工作
iOS Swift 3 CompletionHandler not working
我正在尝试在 Swift 中编写一个完成处理程序函数,这是我在 Swift 中的代码,其中包含一个名为 NBObject
的 class
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()
函数有问题,我只是想不出问题出在哪里。
问题是您在网络请求的完成处理程序之外调用完成处理程序,因此您的函数的完成处理程序 returns 在异步网络请求之前 return。您需要将其移动到请求的完成处理程序中。
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any] {
theData = json
print("JSON: \(json)")
completionHandler(true, theData)
}
}
您必须将完成处理程序放入数据任务的完成处理程序
可以省略URLRequest
的创建,GET是默认的,直接传URL:
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
我正在尝试在 Swift 中编写一个完成处理程序函数,这是我在 Swift 中的代码,其中包含一个名为 NBObject
的 classtypealias 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()
函数有问题,我只是想不出问题出在哪里。
问题是您在网络请求的完成处理程序之外调用完成处理程序,因此您的函数的完成处理程序 returns 在异步网络请求之前 return。您需要将其移动到请求的完成处理程序中。
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any] {
theData = json
print("JSON: \(json)")
completionHandler(true, theData)
}
}
您必须将完成处理程序放入数据任务的完成处理程序
可以省略URLRequest
的创建,GET是默认的,直接传URL:
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