Using Swift Closure. Recursive? - swift

I just have a quick conceptual question about this closure here:
func getRandomUser(onCompletion: (JSON) -> Void) {
let route = baseURL
makeHTTPGetRequest(route, onCompletion: { json, err in
onCompletion(json)
})
}
What does the line onCompletion(json) do exactly? Is this a recursive call to onCompletion?

Let's look at your function line-by-line:
1. func getRandomUser(onCompletion: (JSON) -> Void) {
2. let route = baseURL
3. makeHTTPGetRequest(route, onCompletion: { json, err in
4. onCompletion(json)
5. })
6. }
Line 1: this gives the signature of your function; it takes one argument, and that argument is of type (JSON) -> Void, which means the argument it accepts is a closure that itself takes one argument of type JSON and does not have a return value, i.e. "returns Void", -> Void or -> (); note that the function definition also includes a local parameter name for that argument: within the function body, that closure is assigned to the constant onCompletion
Line 2: constant assignment...
Line 3: this calls the function makeHTTPGetRequest(_:onCompletion:), which takes two arguments: a route (which does not use an external label in the call, hence the _ in the function name as given previously), and a closure - this closure is of type (JSON, NSError?) -> Void; note that on this line where onCompletion occurs, this is the external label required for the second argument when calling the makeHTTPGetRequest(_:onCompletion:) function, there is not any assignment taking place (as occurred on Line 1)
Line 4: the closure assigned to the constant onCompletion is called with one argument...
So while it may be confusing that the text onCompletion occurs twice in this section of code (before the closure is actually invoked on Line 4), there is only one constant that goes by that name - the other occurrence is simply an external label for an argument.
If it helps at all, we can actually eliminate the use of the onCompletion label altogether by taking advantage of Swift's "trailing closure syntax" and rewrite it like so:
func getRandomUser(onCompletion: (JSON) -> Void) {
let route = baseURL
makeHTTPGetRequest(route) { json, err in onCompletion(json) }
}
...but that's a topic for another post :)

The onCompletion parameter of makeHTTPGetRequest is not available in its own scope. It's basically declaring what onCompletion is. It would then be calling onCompletion on getRandomUser.

Related

Best way to define a completion handler for URLSession in Swift

I have a call to a URLSession:
var someVar = "Are you in my scope?"
let task = session.dataTask(with: url, completionHandler: updatePlaces)
Where updatePlaces is a function defined as:
private func updatePlaces(data: Data?, response: URLResponse?, error: Error?) -> Void
I split it up into another function because I really don't like having this as one large block of code with my "updatePlaces" function as a closure in my original session.dataTask. It just seems to be doing too much in one function. I want to split it up.
I can also make a closure using the syntax below, but I see no difference between this and the function (I understand a function is a special type of closure, and I see no difference):
lazy var updatePlaces: (Data?, URLResponse?, Error?) -> Void = {(data, response, error) in
However, earlier you saw I added someVar to the scope. With the function and the lazy var, I do not have access to someVar. However, if I make the closure inside the session.dataTask, someVar is captured and I can reference it per the docs:
Closures can capture and store references to any constants and
variables from the context in which they are defined. This is known as
closing over those constants and variables. Swift handles all of the
memory management of capturing for you.
So... I have two specific questions.
Are there ANY differences between my function declaration and my closure declaration and just passing that to completion handler.
Is there any way to capture the references in the original function if I don't define the closure in it? I'm guessing not.
And a more... generic question: What is the preferred way of handling this?

How do I compose the CoreMidi MIDISendSysex Request in Swift 3?

I'm receiving the error.
Cannot convert value of type '() -> ()' to type 'MIDICompletionProc'
(aka '#convention(c) (UnsafeMutablePointer) ->
()') in coercion.
Everything else looks OK but for the life of me I can't seem to compose the CompletionProc function call.
var mySysExSendRequest : MIDISysexSendRequest
let myCompProc = sysexCompletionProc (a separate static function)
mySysExSendRequest = MIDISysexSendRequest(destination: Dest,
data: dataptr,
bytesToSend: 16,
complete: complete,
reserved: res,
completionProc: sysexCompletionProc as MIDICompletionProc,
completionRefCon: nil)
MIDISendSysex(&mySysExSendRequest)
You're currently supplying a function that takes no arguments, i.e. () -> Void.
Your completion proc must have this signature:
(UnsafeMutablePointer<MIDISysexSendRequest>) -> Void
Also note that since the proc has to be compatible with #convention(c) semantics it cannot be a class method or a closure.
It may be possible to work around that restriction by passing a pointer to self in the completionRefCon field and then casting that back (using "unsafe" methods) within the callback.

What does () mean in Swift?

I have the following function in Swift 3
func fetchOrders(_ completionHandler: (_ orders: [Order]) -> Void)
{
ordersStore.fetchOrders { (orders: () throws -> [Order]) -> Void in
do {
let orders = try orders()
completionHandler(orders)
} catch {
completionHandler([])
}
}
}
What does _ completionHandler argument in fetchOrders mean?
What does (orders: () throws -> [Order]) mean?
PS : I am new to iOS and Swift
There's quite a lot in here, so we'll break it down one piece at a time:
func fetchOrders(_ completionHandler: (_ orders: [Order]) -> Void)
This is a function called fetchOrders.
It has one parameter (completionHandler) and returns nothing.
The first _ indicates that there is no "external name" of the first parameter. That is, you do not have to label it (in fact, you cannot). (For subtle reasons that don't really matter here, I believe the author made a mistake using _ there, and I would not have done that.)
The completionHandler is the "internal name," what the parameter is called inside the function.
The type of completionHandler is (_ orders: [Order]) -> Void. We'll break that down now.
This value is a closure that takes an [Order] (array of Order) and returns Void. Informally this means "returns nothing" but literally means it returns the empty tuple ().
The _ orders: syntax is in practice a comment. In principle the _ is an external name (but that's the only legal external name for a closure), and orders is an internal name, but in reality, closures parameters do not have names in any meaningful way, so this is purely informational.
I believe this is a poor use of the closure parameter commenting system. Since orders tells us nothing more than [Order], I would have omitted it, and made the type just ([Order]) -> Void.
Now we'll turn to the next line:
ordersStore.fetchOrders { (orders: () throws -> [Order]) -> Void in
This calls the fetchOrders method on ordersStore. We can tell from this code that fetchOrders takes a closure parameter. This is called "trailing closure" syntax in Swift, and is why I would not have used the _ for our closure. With trailing closure syntax, the external name of the parameter is not needed.
The author has provided type information here that probably wasn't necessary, but we can explore it anyway. This could likely have been written as just { orders in, but then the reader would probably have been surprised by this somewhat unusual code.
We have been passed a closure called orders that takes nothing and returns [Order] or throws an error. Basically this is a way to say that fetchOrders might fail.
The author is working around an awkwardness in Swift's throws system, which does not have a natural way to express an asynchronous action that might fail. This is one way to fix it; you pass a throwing (i.e. a possibly failing) function. I don't favor this approach, I favor using a Result enum for this case because I think it scales better and avoids possible unintended side effects, but that's a debatable point (and the Swift community hasn't really decided how to deal with this common problem).
This all leads us to:
do {
let orders = try orders()
completionHandler(orders)
} catch {
completionHandler([])
}
This is where the orders closure is evaluated. (This is very important; if orders has side effects, this is when they occur, which may be on a different queue than was intended. That's one reason I don't favor this pattern.) If the closure succeeds, we return its result, otherwise we return [] in the catch below.
In this particular case, the throws approach is slightly silly, because it's silently flattened into [] without even a log message. If we don't care about the errors, then failure should have just returned [] to start with and not messed with throws. But it's possible that other callers do check the errors.
In either case, we call the completionHandler closure with our result, chaining this back to our original caller.
This do/catch block could have been more simply written as:
let completedOrders = try? orders() ?? []
completionHandler(completedOrders)
This makes it clearer that we're ignoring errors by turning it into an optional, and avoids code duplication of the call to completionHandler.
(I just add the extra let binding to make the code a little easier to read; it isn't needed.)
The completionHandler argument means that the expected parameter (named completionHandler) must be a function that takes a list of Order objects and does not return any value.
completionHandler is the a variable name. In this specific example, this variable is a callback. You know is a callback function because (orders: [Order]) -> Void is it's data type; in this particular case, said data type is a function that receives an array of Order objects in a variable _orders and doesn't have a return value (the Void part).
TL;DR:
it's the variable name, of type:
function which receives an array of Order as a parameter and acts as a callback.

Method parameters in nested closure

I am trying to understand how parameters passed to a method are available to nested closures. I'm nervous that something I wrote won't always have the original parameters available.
(these are drastically simplified examples)
I have a method that I wrote that specifies a closure as a parameter:
func saveNameAndAgeToServer(serverParams: [String:String], completionHandler: (age: NSNumber) -> ()) {
// Connect to a server
// POST a name and dob from serverParams
// Receives a current age in completion:
completionHandler(age: 22)
}
Now somewhere else I create another method, that also specifies a closure, takes two parameters and calls the first function:
func AwesomeFunc(name: String, dob: NSDate, completionHandler: (isOverTwentyOne: Bool) -> ()) {
let formattedDob = NSDateFormatter().stringFromDate(dob)
saveNameAndAgeToServer([name:formattedDob]) { (age) -> () in
if (age as Int) >= 21 {
print("\(name) can have a beer.")
completionHandler(isOverTwentyOne: true)
} else {
print("\(name) is too young to drink, he can have a water.")
completionHandler(isOverTwentyOne: false)
}
}
}
Am I able to guarantee that the parameters (name and dob) passed into this latter function will always be available?
What I'm trying to ask is will the memory that the saveNameAndAgeToServer closure runs within always have the parameters of AwesomeFunc available to it? I'm pretty sure the function is all being held while whatever it calls is completed but would love a 2nd opinion.
You are correct, captured variables will last for the life of the closure. Here's an exert on capturing variables from apple's swift documentation:
A closure can capture constants and variables from the surrounding
context in which it is defined. The closure can then refer to and
modify the values of those constants and variables from within its
body, even if the original scope that defined the constants and
variables no longer exists.
In Swift, the simplest form of a closure that can capture values is a
nested function, written within the body of another function. A nested
function can capture any of its outer function’s arguments and can
also capture any constants and variables defined within the outer
function.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html

Can you help me understand this Swift method?

I am building an app using Swift for the first time and using the AlamoFire library. I've built apps using Obj-C and AFNetworking before, but I'm having a hard time groking this Swift response method:
Alamofire.request(.GET, "http://someapi.com/thing.json")
.responseJSON { _, _, JSON, _ in
println(JSON)
}
The actual method definition is:
public func responseJSON(options: NSJSONReadingOptions = .AllowFragments, completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return response(serializer: Request.JSONResponseSerializer(options: options), completionHandler: { request, response, JSON, error in
completionHandler(request, response, JSON, error)
})
}
I don't really understand what's going on here when I use this response method.
Why am I not using parens in the method call?
Am I just passing a block or anonymous function into this method?
What is the significance of passing underscores (_)?
What is the in keyword doing?
It's all here:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID102
No parens: that's trailing closure syntax. Idea is that closures can get long, hard to remember/determine long-distance paren pair.
Yes, block = anonymous function = (anonymous) closure. Yes, you're passing that as the only parameter. Since it's omitted, 'options' gets its default value of '.AllowFragments'. Trailing closure { ... } gets bound to completionHandler parameter.
The '_' is the 'don't care about this parameter' syntax ... e.g. if the function doesn't use the parameter, no point to giving it a local name.
in is part of closure syntax: indicates start of function body. Definitely read the whole closure syntax chapter above. It's designed to be extremely terse, nothing intuitive about it.