如何调用包含完成处理程序的函数?

Posted

技术标签:

【中文标题】如何调用包含完成处理程序的函数?【英文标题】:How do I call my function that contains a completion handler? 【发布时间】:2016-02-23 18:28:00 【问题描述】:

由于我的大多数应用程序都使用异步的 rest api 调用,因此仍在尝试掌握完成处理程序的窍门。我的项目使用AlamofireSwiftyJSON 我有一个类函数,它接受我想用来调用我的POST api 并将值插入数据库的参数。 API 返回插入的新行的 ID。我想将响应作为从函数返回的 swifty JSON 对象。这是函数:

class func insertItem(item: String, description: String, quantityOnHand: Int, reorderPoint: Int, supplier_id:Int, completionHandler: JSON -> Void) 

    let urlEndpoint = Constants.Urls.Inventory.Add
    let newItem = ["item": item, "description": description, "quantityOnHand": quantityOnHand, "reorderPoint": reorderPoint, "supplier_id": supplier_id]

    Alamofire.request(.POST, urlEndpoint, parameters: (newItem as! [String : AnyObject]), encoding: .JSON)
        .responseJSON  response in
            guard response.result.error == nil else 
                //got an error, need to handle it
                print(response.result.error!)
                return
            

            completionHandler(JSON(response.response!))
    


我正在尝试调用此函数,但我不确定为完成参数添加什么:

Inventory.insertItem("NewFromFunc", description: "new function!!!", quantityOnHand: 400, reorderPoint: 1, supplier_id: 2, completionHandler: ???)
    

编辑:更新了现在的功能。完成后无法返回任何内容:

    func insertItem(item: String, description: String, quantityOnHand: Int, reorderPoint: Int, supplier_id:Int, completionHandler: (JSON) -> Void) 

        let urlEndpoint = "http://url"
        let newItem = ["item": item, "description": description, "quantityOnHand": quantityOnHand, "reorderPoint": reorderPoint, "supplier_id": supplier_id]

        Alamofire.request(.POST, urlEndpoint, parameters: ((newItem) as! [String : AnyObject]))
            .responseJSON  response in
                //print(newItem)

                guard response.result.error == nil else 
                    //got an error, need to handle it
                    print("Error thread")

                    return
                
                if let value: AnyObject = response.result.value 
                    //hande results as JSON without bunch of nested if loops
                    let statusCode = response.response?.statusCode
                    if statusCode == 201 

                        //let newid = value["id"]
                        //let status = value["status"]

                        print("Status is 201")
                        print(value)
                    
                    else 
                        print("there's an issue returning data")
                    
                
                completionHandler(JSON(response.response!))
            
    

【问题讨论】:

【参考方案1】:

您需要设置完成处理程序的类型。你的似乎有一个 JSON 类型的参数,所以像这样

completionHandler: (JSON) -> Void

要使其成为可选,您可以这样做

completionHandler: ((JSON) -> Void)?

然后你会这样打电话

Inventory.insertItem("NewFromFunc", description: "new function!!!", quantityOnHand: 400, reorderPoint: 1, supplier_id: 2) data in 
    //Do something with the data object

这也可以通过创建一个 typeAlias 来完成,如果您要拥有多个具有相同类型处理程序等的方法

这是一个示例,说明我如何在我的 rest 客户端类中使用 typealias,因为响应用于多种方法

typealias ServiceResponse = (JSON, NSError?) -> Void

class RESTClient : NSObject 
    static let sharedInstance = RESTClient()

    func makeRequest(type: String, endPoint: String, parameters: [String: AnyObject]?, onCompletion: ServiceResponse)
        makeRequest(type, endPoint: endPoint, parameters: parameters, files: nil, onCompletion: onCompletion)
    
...

【讨论】:

但是我调用它时如何获取函数返回的JSON呢?它是否存储在data 变量中?我试过用data["id"] 抓住它,但没有任何效果。假设该函数返回 JSON 数据。添加完成处理程序导致我将其更改为返回 void。如何返回数据?谢谢! 根据值的类型,您应该能够执行类似 data["id"].string 的操作。这将返回一个可为空的字符串。如果你确定它不为空,你可以使用 stringValue 来解开它。这些方法适用于各种类型(int、number、bool 等)【参考方案2】:

您可以创建一个新类 P>

导入 UIKit

typealias ServiceResponse =(!,NSDictionary的NSError!) - >空隙 P>

类AFNInjector:NSObject的

func getDataWith(parameters:NSDictionary, url:String, onCompletion: ServiceResponse) -> Void 

    let manager:AFHTTPRequestOperationManager = AFHTTPRequestOperationManager()
    let serializer:AFJSONRequestSerializer = AFJSONRequestSerializer()
    manager.responseSerializer.acceptableContentTypes = NSSet(objects:"text/html") as NSSet as Set<NSObject>
    manager.requestSerializer = serializer
    manager.POST(url, parameters: parameters, success:  (operation: AFHTTPRequestOperation!, responsobject: AnyObject?) -> Void in
        let data = responsobject as! NSDictionary?
        onCompletion(data,nil)
    )  (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
        let errorObject = error as NSError?
        onCompletion(nil,errorObject)
    

之后,你可以调用这个 P>

    let Obj=AFNInjector()
    let parameters:NSDictionary = ["apicall":"Login","password":txtPassword.text,"email":txtEmail.text]

   Obj.getDataWith(parameters, url:BASEURL)  (result, error) -> Void in
        if (result != nil)


            print(result)


           
        else



        
    

【讨论】:

以上是关于如何调用包含完成处理程序的函数?的主要内容,如果未能解决你的问题,请参考以下文章

Swift:如何调用其中一个参数是完成处理程序的函数

如何在完成处理程序中传递数据

如何在 SwiftUI 的列表项中调用完成处理程序?

SwiftUI - 如何通过视图模型完成调用函数

PostMessage 不会触发消息处理程序

从不调用函数的完成处理程序有啥影响?