【问题标题】:Additonal parameters for data task completion handler in SwiftSwift 中数据任务完成处理程序的附加参数
【发布时间】:2017-09-06 18:30:05
【问题描述】:

我是 Swift 的新手。当按下按钮时,我的视图控制器会调用 Web 服务类的方法。该方法依次调用 dataTask(),并提供一个完成处理程序:

    let task = session.dataTask(with: request as URLRequest) { data, response, error in
        guard error == nil && data != nil else {
            print(error ?? "")
            return
        }

        // print(JSON(data:data!))
        print ("data : ", data ?? "-- no data --")
        print ("response : ", response ?? "-- no response --")
        print ("error : ", error ?? "-- no error --")

完成处理程序需要更新视图控制器的 GUI。但是,处理程序似乎只采用三个标准参数。如何将视图控制器引用传递给它?处理程序无法执行 self.someTextView.update(.....) 来更新 GUI,因为它在 Web 服务类中,而不是在视图控制器中。

有什么想法吗?谢谢。

【问题讨论】:

  • 请添加更多代码,我不知道你把那个任务放在哪里
  • 闭包从调用方法中捕获对象和值,所以使用self或者在let task ...之前使用你需要的引用创建一个变量
  • 假设你的视图控制器有一个对这个网络服务类的引用,在它们之间做一个委托或者一个回调函数。
  • 谢谢。找到了解决方案。将视图控制器引用传递给 Web 服务类,并将其作为实例变量保存在那里,以供完成处理程序使用。

标签: swift parameters completionhandler


【解决方案1】:

dataTask(with:completionHandler:)中所述:

此完成处理程序采用以下参数:

data

服务器返回的数据。

response

提供响应元数据的对象,例如 HTTP 标头和 状态码。如果您正在发出 HTTP 或 HTTPS 请求,则返回的 object 实际上是一个 HTTPURLResponse 对象。

error

一个错误对象,指示请求失败的原因,如果请求失败,则返回 nil 请求成功。

这意味着 - 显然 - 它与 UIViewController 无关。

因此,如果您想将“ViewController”层包含到此类流程中,您可以实现自己的包装器来执行此类任务,例如,您可以创建一个接受完成参数的函数 - 作为转义闭包-,如下:

func request(completion: @escaping () -> ()) {
    let task = session.dataTask(with: request as URLRequest) { data, response, error in
        guard error == nil && data != nil else {
            print(error ?? "")
            return
        }

        // print(JSON(data:data!))
        print ("data : ", data ?? "-- no data --")
        print ("response : ", response ?? "-- no response --")
        print ("error : ", error ?? "-- no error --")

        // now you could call the "completion" parameter:
        completion()
    }
}

在您的视图控制器中,您可以将其称为:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        request {
            // now you could update your textview:
            self.someTextView.update(.....)
        }

    }
}

您可以声明request的签名以满足您的需求...

【讨论】:

    【解决方案2】:

    您可以发布一个本地通知,它会点击一个方法和在 UIViewController 类中声明的该方法。

    这是代码:

    在 web 服务类中:在 Completion Handler 中:

    NotificationCenter.default.post(名称: Notification.Name("Notification_NAME_HERE"),对象:无,用户信息: 无)

    在 UIViewController 类中:在 viewDidLoad 中:

    NotificationCenter.default.addObserver(自我,选择器: #selector(notificationHandler(notification:)),名称:Notification.Name(Notification_NAME_HERE),对象:nil)

    在 UIViewController 类中添加一个 notificationHandler 方法:

    func notificationHandler(通知:通知) { //这里更新ui }

    这个方法会被 Completion Handler 触发,同时你可以更新你的 UI 或者你想做的任何事情到 UIViewController 类中。

    我认为这对你会有帮助。

    【讨论】:

      【解决方案3】:

      不确定,但是如何使用捕获值呢? 有点像……

      ...code...
      var somevar = 3
      ....whateverblock { [unowned somevar], (default parameters of the blcok) in
      somevar = 4
      ...code...
      }
      

      我没有测试这个,所以不确定它是否会起作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多