在Swift中,如何在已经使用One的函数中使用Completion Handler?

时间:2018-04-28 02:21:03

标签: swift closures return-value completionhandler

标题很可能没有措辞正确,但我会发布我的代码,你可以自己判断......

我想从一个有闭包的函数返回一个String(该闭包从另一个函数获取一个值:

    //call the ServerTimeReturn function and print the results------------ current, from
func handleDateAndTimeFetch() -> String {

    var thisIsTheDate : String?

    serverTimeReturn { (getResDate) -> Void in //Handles the value received from Google and formats it

        let dFormatter = DateFormatter()
            dFormatter.dateStyle = .short
            dFormatter.timeStyle = .medium
            dFormatter.timeZone = TimeZone(abbreviation: "UTC")

        thisIsTheDate = dFormatter.string(from: getResDate!)
    }
        if thisIsTheDate != nil {
            return thisIsTheDate!
        } else {return "AppDelegate > handleDateAndTimeFetch() > 'thisIsTheDate' was not passed a value (was nil)"}
} //End of function


//Call Google's server for the current date & time in UTC (Coordinated Universal Time)----------------------------
func serverTimeReturn(completionHandler:@escaping (_ getResDate: Date?) -> Void){

    let url = URL(string: "https://www.google.com")
    let task = URLSession.shared.dataTask(with: url!) {(data, response, error) in
        let httpsResponse = response as? HTTPURLResponse
        if let contentType = httpsResponse?.allHeaderFields["Date"] as? String {

            let dFormatter = DateFormatter() //A formatter object
            dFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss z"

            let serverTime = dFormatter.date(from: contentType)
            completionHandler(serverTime)

            guard let _ = data, error == nil else {
                print(error ?? "Unknown error")
                return
            }

        }
    }
        print("Retrieved date value")
    task.resume()
}

总结以上内容,我在其他地方拨打handleDateAndTimeFetch(),当它被呼叫时,IT会拨打serverTimeReturn,从Google服务器检索当前日期和时间。 serverTimeReturn使用completionHandler确保在将数据返回到handleDateAndTimeFetch()中的调用之前检索数据。现在回到handleDateAndTimeFetch(),我做了一些格式化,然后将它分配给值thisIsTheDate(我在闭包之外定义,以便handleDateAndTimeFetch()可以将它返回到我开始的位置这整个过程在其他地方。

问题是,我认为handleDateAndTimeFetch()在完成从thisIsTheDate收集之前尝试返回serverTimeReturn,因为该值始终为'nil'并且它会打印else声明。

我的问题是,当我在serverTimeReturn内拨打handleDateAndTimeFetch()时,如何在其中添加completionHandler,以便在我返回{{1}之前确定有值字符串?

相信我,我已经非常努力地想出来了,但我的新手心态不允许它哈哈。

非常感谢!

1 个答案:

答案 0 :(得分:1)

完成服务器方法并不意味着你可以直接在另一种方法中使用它,对serverTimeReturn的调用是异步的,所以你不能返回字符串直接来自handleDateAndTimeFetch,您必须为handleDateAndTimeFetch

设置完成
func handleDateAndTimeFetch(completionHandler:@escaping (_ getResDate: String?) -> Void) {
     serverTimeReturn { (getResDate) -> Void in //Handles the value received from Google and formats it

        let dFormatter = DateFormatter()
        dFormatter.dateStyle = .short
        dFormatter.timeStyle = .medium
        dFormatter.timeZone = TimeZone(abbreviation: "UTC")
        let thisIsTheDate = dFormatter.string(from: getResDate!)
        completion(thisIsTheDate)
  }
}

或者在serverTimeReturn中进行所有格式化并返回字符串(我推荐),因为不需要执行2个函数来等待相同的异步任务