我正在尝试从Swift中的PHP脚本获取返回值。然而,我似乎一直收到这个错误:
在展开可选值时意外发现nil
下面是这个类:
var value: String!
func run(idNumber: Int) {
let request = NSMutableURLRequest(url: URL(string: "https://mywebsite.com/file.php")!)
request.httpMethod = "POST"
let postString = "a=Hello"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
//answer = error;
}
let answerString = String(data: data!, encoding: String.Encoding.utf8)
self.value = answerString
}
task.resume()
}
func getValue() -> String{
return value
}
调用getValue()
函数时出现错误。但是,当我一创建"answerString“就将其打印出来时,它就成功地打印出来了!
这些函数在这里调用:
let access = ApiAccess()
access.run(idNumber: 0)
print(access.getValue())
发布于 2018-08-21 09:00:04
发出请求是一个异步任务。调用getValue
之前,需要等待闭包回调被调用。
您可以向run
方法添加闭包回调。这样,您就可以知道请求何时完成,并且可以打印结果:
var value: String!
func run(idNumber: Int, @escaping callback: () -> Void) {
let request = NSMutableURLRequest(url: URL(string: "https://mywebsite.com/file.php")!)
request.httpMethod = "POST"
let postString = "a=Hello"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
//answer = error;
}
let answerString = String(data: data!, encoding: String.Encoding.utf8)
self.value = answerString
callback()
}
task.resume()
}
func getValue() -> String{
return value
}
let access = ApiAccess()
access.run(idNumber: 0) {
print(access.getValue())
}
发布于 2018-08-21 09:01:19
问题是URLSession.shared.dataTask()
的回调是异步发生的,所以在设置var value
之前,您最终将执行access.getValue()
。这意味着value
在具有值之前被强制解包,这会导致此错误。
要解决此问题,请考虑使用promises、RxSwift或类似的异步工具,以便仅在可用时访问值。
发布于 2018-08-21 09:10:25
重构您的run(idNumber:)
函数以获取完成处理程序:
func run(idNumber: Int, completion: (String?, Error?)-> Void ) {
let request = NSMutableURLRequest(url: URL(string: "https://mywebsite.com/file.php")!)
request.httpMethod = "POST"
let postString = "a=Hello"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
completion(nil, error)
}
let answerString = String(data: data!, encoding: String.Encoding.utf8)
self.value = answerString
completion(answerString, nil)
}
task.resume()
}
然后这样叫它:
let access = ApiAccess()
access.run(idNumber: 0) { result, error in
guard let result = result else {
print("No result. Error = \(error)")
return
}
print("result = \(result)")
}
(或者使用Futures或Promises,@JohnEllmore在他的回答中提到)
https://stackoverflow.com/questions/51940202
复制相似问题