2

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.

Jakub Truhlář
  • 20,070
  • 9
  • 74
  • 84

3 Answers3

2

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I would suggest filing a bug at bugs.swift.org if you don't like the way the generated interface is generated. – matt Jan 07 '17 at 02:47
  • 1
    Thank you, have to deduce the meaning of these parameters is questionable choice. It did not even auto insert labels in their closures anymore. – Jakub Truhlář Jan 07 '17 at 09:43
1

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.

Community
  • 1
  • 1
Alexander
  • 59,041
  • 12
  • 98
  • 151
1

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.

Caleb Kleveter
  • 11,170
  • 8
  • 62
  • 92
  • Sure, you can name argument labels as you want, do not have to use the same labels provided by function closures (In a closure passed as a function parameter). You can do the same in Obj-C as well. But the thing about the example above is that it is not always obvious (completion with bool) and documentation did not say a thing about it. How come? – Jakub Truhlář Jan 06 '17 at 22:19
  • 1
    Because it's been overlooked :( – Alexander Jan 06 '17 at 22:21