Usage of closures with multiple arguments in swift

流过昼夜 提交于 2019-12-06 07:07:09
venueService.someFunctionThatTakesAClosure({
  venues, error in
  // do stuff
})

you can optionally specify the types (but since the compiler knows what types the closure is supposed to provide, you don't strictly have to:

venueService.someFunctionThatTakesAClosure({
  (venues: Dictionary<String, AnyObject>, error: NSError) -> () in
  // do stuff
})

But I see another issue in your calling code:

completionClosure(venues: responseDictionary, error: error!)
//            No Bueno. What if there's no error?    ^^^^^^

You shouldn't force unwrap the error since it's entirely possible that it's still nil. Force unwrapping nil will cause an error. So you want this:

completionClosure(venues: responseDictionary, error: error)

AND you want to change your closure to take an optional error. In total:

func someFunctionThatTakesAClosure(completionClosure: (venues: Dictionary<String, AnyObject>, error: NSError?) -> ()) {
    …
    completionClosure(venues: responseDictionary, error: error)
}

// when calling:
venueService.someFunctionThatTakesAClosure({
  (venues: Dictionary<String, AnyObject>, error: NSError?) -> () in
  // do stuff
})

If you'd like to pass additional arguments, keep in mind swift is optimized for closures to be passed as the last argument (and it's a widely followed convention in objective-c APIs):

// in venueService:
func someArgAndClosureFunction(arg1: String, arg2: Int, 
                  completionClosure: (venues: Dictionary<String, AnyObject>, error: NSError?) -> ()) {
    // do stuff
}

// When calling:
venueService.someArgAndClosureFunction("string arg 1", arg2: 10) {
  (venues: Dictionary<String, AnyObject>, error: NSError?) -> () in
  // do stuff
}

In this example I've used the trailing closure syntax which allows you pass the closure outside the function call parens (but it is still passed as the last argument).

As your error is optional, I would make it an optional argument of the passed function:

func someFunctionThatTakesAClosure(completionClosure: (venues: Dictionary<String, AnyObject>, error: NSError?) -> ()) {
  // function body goes here
  var error: NSError? = nil
  let responseDictionary: Dictionary<String, AnyObject> = ["test" : "test2"]
  completionClosure(venues: responseDictionary, error: error)
}

It can then be invoked, passing a closure as follows:

someFunctionThatTakesAClosure { println($0); println($1) }

Note, the above is one of the shorthand syntax variants for creating closures.

I think you were probably just tired :)

You're saying that the difficulty you are having is in calling the method, right? None of the examples you gave are passing a valid argument, which should be a closure of type:

(Dictionary<String, AnyObject>, NSError) -> ()

So there are a couple of things you could do...

(a) assign a conforming closure to a variable and pass the variable as the argument to the method:

let myClosure: (Dictionary<String, AnyObject>, NSError?) -> () = { venues, error in
    for (key, _) in venues {
        println(key)
    }
}

venueService.someFunctionThatTakesAClosure(myClosure)

(b) pass a trailing closure as the argument to the method call:

venueService.someFunctionThatTakesAClosure {
    venues, error in
    for (key, _) in venues {
        println(key)
    }
}

The syntax for passing in parameters to closures revolve around the in keyword.

Sorry for the link url...but check out http://fuckingclosuresyntax.com/ and notice in the options where in appears.

see array.sort({ (item1, item2) in return item1 < item2 })

Which takes in item1 and item2 as 2 inputs

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!