Jakub Truhlář
Jakub Truhlář

Reputation: 20710

Why Apple's closure declarations missing argument labels

As I read through the UIKit, most of the time I see closures (as a function parameter) with missing argument labels like this: func fooClosure(fooClosure: (Bool) -> Swift.Void)

In some cases I can guess what it stands for, in others I can't.

Example:

Take a look at one of UIActivityViewController's closure (as a type alias):

public typealias UIActivityViewControllerCompletionWithItemsHandler = (UIActivityType?, Bool, [Any]?, Error?) -> Swift.Void

What does 3rd type stand for? I have to look at the Objective-C version of the code to know these are returnedItems.

Why it is not implemented that way: (note the activityItems label)

public typealias UIActivityViewControllerCompletionWithItemsHandler = (UIActivityType?, Bool, _ activityItems: [Any]?, Error?) -> Swift.Void

Edit: - Is this just a temporary state (since the Swift is not fully integrated in these frameworks yet)? Code is less readable without argument labels.

Upvotes: 2

Views: 965

Answers (3)

matt
matt

Reputation: 534903

The problem is that this is a function signature typealias generated by machine, and the machine isn't doing what you would like it to do. Consider the following Objective-C declaration:

typedef void (^MyCoolType)(NSString* __nullable name);

The Swift generated interface for that is:

public typealias MyCoolType = (String?) -> Swift.Void

As you can see, name got stripped out; it is nowhere to be seen.

Nothing stops you from defining a function signature typealias with internal labels, in Swift. This is legal:

public typealias MyCoolType = (_ name:String?) -> Void

But that does not happen to be how the generated interface is generated from Objective-C.

Upvotes: 2

Caleb Kleveter
Caleb Kleveter

Reputation: 11494

Closures are designed to be versatile. You don't have parameter names because the function you create to pass in could be wildly different from the function someone else rights.

Remember, the parameter names belong to the function.

To illustrate, when I create a function, I would do it like this:

func getUser(for name: String) -> User {
    // Stuff here...
}

I add the label so myself and others know how to properly use the function.

A closure parameter is not a function, you pass in a function. The function one person writes could create a cheese burger, while another person could write one that rotates a view 180º and segue to a new view controller.

With an example from Apples Documentation on UIView, there is an ending closure called completion. As this name suggests, this function is fired when the animation completes. Now the docs do explain that the Bool value tells you whether the animation is complete or not, something that is not obvious from the function itself.

If your not sure what the parameter is used for (example being above), look at the docs.

Hope this answers your question.

Upvotes: 1

Alexander
Alexander

Reputation: 63157

As of Swift 3, keywords are no longer a part of a closure's type, thus they don't (and can't) appear anywhere a type is expected, such as in type alias and func declarations.

See the answer in this post for more information.

Upvotes: 1

Related Questions