【问题标题】:Getting a value from web call in Swift [duplicate]从 Swift 中的网络调用中获取价值 [重复]
【发布时间】:2019-01-27 03:23:58
【问题描述】:

我正在尝试从 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())

【问题讨论】:

  • 调用getValue()的代码在哪里?
  • @JohnEllmore 我为丢失的代码道歉。我已经编辑了帖子。

标签: ios swift


【解决方案1】:

发出请求是一项异步任务。在调用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())
}

【讨论】:

    【解决方案2】:

    重构您的 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 在他的回答中提到的那样)

    【讨论】:

      【解决方案3】:

      问题是URLSession.shared.dataTask() 的回调是异步发生的,因此您最终会在设置var value 之前执行access.getValue()。这意味着value 在它有值之前被强制解包,这会导致此错误。

      要解决此问题,请考虑使用 Promise、RxSwift 或类似的异步工具,以便仅在可用时访问值。

      【讨论】:

        猜你喜欢
        • 2017-11-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-10
        • 2015-07-23
        • 2012-09-19
        • 2016-01-26
        • 2019-03-25
        相关资源
        最近更新 更多