swift 3中的回调语法

时间:2017-08-18 12:47:32

标签: swift swift3 closures

我正在尝试在swift 3上创建一个回调,但到目前为止还没有任何运气。我正在看一下这个问题:link这是类似的,但答案给了我一个错误。

基本上我有一个带有静态函数的API结构,我需要回调。

import UIKit

struct API {
 public static func functionWithCallback(params: Dictionary<String, String>, success: @escaping ((_ response: String) -> Ticket), failure: @escaping((_ error:String) -> String) ) {
        let app_server_url = "http://api.com" + params["key"]!

        let url: URL = URL(string: app_server_url)!
        var request: URLRequest = URLRequest(url: url)
        request.httpMethod = "POST"
        do {
            request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)

        } catch let error {
            print(error.localizedDescription)
        }

        request.addValue("application/json charset=utf-8", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json charset=utf-8", forHTTPHeaderField: "Accept")

        let session = URLSession.shared

        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in

            guard error == nil else {
                return
            }

            guard let data = data else {
                return
            }

            DispatchQueue.main.async {
                do {
                    let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
                    print(json)
                    var message = ""

                    if let result = json["result"] as? String {
                        if(result == "success") {
                            //attempt to call callback gives me an error: extra argument in call
                            success("") {
                               let ticket = json["ticket"] as! NSDictionary
                               var date = ticket["date"] as! String
                               var ticket: Ticket = nil
                               ticket.setDate(date: date)
                               return ticket
                            }
                    }
                    else {
                        message = json["message"] as! String
                        print(message)
                    }
                } catch let error {
                    print(error.localizedDescription)

                    let description = error.localizedDescription
                    if let data = description.data(using: .utf8) {
                        do {
                            let jsonError = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
                            let message = jsonError?["message"] as! String
                        } catch {

                        }
                    }
                }
            }
        })
        task.resume()
    }

}

所以我基本上无法调用回调成功,因为它给了我一个错误:调用中的额外参数。有关如何修复的想法吗?

我的目标是致电:

API.functionWithCallback(params: params, success() -> Ticket {
    //do something with the returned ticket here
},
error() -> () {
   //do something with the error message here
}
)

2 个答案:

答案 0 :(得分:2)

我相信你对如何使用回调闭包有错,从我能理解你的问题你想要在回调闭包中对票做一些事情并且这样做它应该是闭包的一个参数不是封闭的返回类型。

用以下代码替换你的函数声明:

public static func functionWithCallback(params: Dictionary<String, String>, success: @escaping ((_ response: String, _ ticket: Ticket) -> Void), failure: @escaping((_ error:String) -> Void) ) {

在函数内部替换:

success("") {
    let ticket = json["ticket"] as! NSDictionary
    var date = ticket["date"] as! String
    var ticket: Ticket = nil // Im not sure what you are trying to do with this line but this will definitely give an error
    ticket.setDate(date: date)
    return ticket
}

使用:

let ticket = json["ticket"] as! NSDictionary
var date = ticket["date"] as! String
var ticket: Ticket = nil // fix this line
ticket.setDate(date: date)
success("",ticket)

然后你可以这样调用这个函数:

API.functionWithCallback(params: params, success: { response, ticket in
    // you can use ticket here
    // and also the response text 
}) { errorMessage in
    // use the error message here
}

答案 1 :(得分:0)

试试这个:

func uploadImage(api: String,token : String, methodType : String,  requestDictionary: [String:AnyObject],picData:[Data], successHandler: @escaping (AnyObject) -> Void,failureHandler: @escaping (NSError) -> Void)
{

    if Common_Methods.Reachability1.isConnectedToNetwork() == false
    {

        let del :AppDelegate = (UIApplication.shared.delegate as? AppDelegate)!

        let nav : UINavigationController = (del.window?.rootViewController as? UINavigationController)!

        let alert = UIAlertController(title: "", message: "The Internet connection appears to be offline" , preferredStyle: UIAlertControllerStyle.alert)

        // Create the actions
        let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default)
        {
            UIAlertAction in

        }

        alert.addAction(okAction)
        nav.present( alert, animated: true, completion: nil)

        return
    }

    let apiUrl = "\(KbaseUrl)\(api)"
    let session = URLSession.shared
    let url: NSURL = NSURL(string: apiUrl as String)!
    print(url)
    let request = NSMutableURLRequest(url: url as URL)
    request.httpMethod = methodType
    let boundary = NSString(format: "---------------------------14737809831466499882746641449") as String

    //-------- add token as perameter and set a check if token not nill then set token in header -------


    if(token.characters.count > 0)
    {
        request.setValue(token, forHTTPHeaderField: "x-logintoken")
    }

    request.setValue("Keep-Alive", forHTTPHeaderField: "Connection")
    request.setValue("multipart/form-data; boundary="+boundary, forHTTPHeaderField: "Content-Type")
    let data = createBodyWithParameters(parameters: requestDictionary, filePathKey:nil, imageDataKey: picData.count > 0 ? picData : [], boundary: boundary)
    print(data)
    request.httpBody = data

    let task = session.dataTask(with: request as URLRequest) { data, response, error in

        // handle fundamental network errors (e.g. no connectivity)

        guard error == nil && data != nil else {
            successHandler(data as AnyObject )//completion(data as AnyObject?, error as NSError?)
            print(error)
            DispatchQueue.main.async {
                Common_Methods.hideHUD(view: (topVC?.view)!)
            }
            return
        }

        // check that http status code was 200

        if let httpResponse = response as? HTTPURLResponse , httpResponse.statusCode != 200 {





            do {
                let responseObject = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary


                if let responseDictionary = responseObject as? [String:AnyObject]
                {
                    if responseDictionary["statusCode"] as! Int == 401
                    {

                        // self.objDelegate.sessionExpire(msgStr: "Session Expired. Please login again to continue.")




                    }
                    else
                    {
                        //completion(String(data: data!, encoding: String.Encoding.utf8) as AnyObject?, nil)

                    }

                }

            } catch let error as NSError {
                print(error)
                DispatchQueue.main.async {
                    Common_Methods.hideHUD(view: (topVC?.view)!)
                }
                //  completion(String(data: data!, encoding: String.Encoding.utf8) as AnyObject?, nil)
            }



        }

        // parse the JSON response

        do {
            DispatchQueue.main.async {
                Common_Methods.hideHUD(view: (topVC?.view)!)
            }
            let responseObject = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary
            successHandler(responseObject! )
        } catch let error as NSError {
            DispatchQueue.main.async {
                Common_Methods.hideHUD(view: (topVC?.view)!)
            }
            //  completion(String(data: data!, encoding: String.Encoding.utf8) as AnyObject?, error)
            failureHandler(error)
        }
    }
    task.resume()

    //  return task


}

和函数调用是:

WebService.sharedInstance.uploadImage(api: KEditEmployerProfile,token: token,methodType: "PUT", requestDictionary: parameters1 as! [String : AnyObject], picData: [imageData as Data], successHandler: { (responseObject) in
 print(responseObject)
    }) { (error) in
                print(error)
        }
      }