Xcode 8 :Function Types Cannot Have Argument Label Breaking My Build

Xcode 8 :function types cannot have argument label breaking my build

The Swift designers decided to prohibit argument labels for function types.

The reasoning is explained here: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

This is a frustrating and questionable choice, as prohibiting argument labels makes it much easier to incorrectly invoke closures, which seems more important than simplifying the language's type system.

Usability > ideology.

Xcode requires to put _ before return value name in completion handler

Since some version of Swift, closure types can't have parameter names. However, there is a workaround:

typealias Result = String

And now you can use Result as the closure type:

func f(completion: (Result) -> Void) { ... }

Many methods in Foundation also does this. For example TimeInterval is just an alias for Double, but naming it TimeInterval makes the purpose clearer.

why does the argument label become irrelevant in this Swift code?

Fact: any function in Swift can be reduced to a closure, and they actually are when passed around. f and g and h can all be reduced to closures of type (String) -> String.

Next, your (some_computation)("hello") code what in fact does is to tell to the compiler that you want to create an anonymous function (aka closure), that you call with the "hello" argument.

And due to the above, (0 < 100 ? g : h)("hello") instructs the Swift compiler to transform the g and h functions to closures of type (String) -> String. And closures don't have argument labels, thus any function, with any label, matches.

However, in the problematic code snippet, the compiler can no longer uniquely identify which h "overload" to use. Thus, it bails out.

If you want to unambiguously match one of the h functions, then you need to fully qualify it:

(0 < 100 ? g : h(foo:))("hello")

The rules work the same for member functions, as long as the compiler can decide which closure to pass along, it will match the function name, without having to specify its complete name.

Main point is that in Swift you don't circulate functions, you circulate closures. There's no way to specify a variable, or a function argument, or a property, to have labeled arguments.

When we should have argument label in Swift function design, and when we should omitting argument label?

In terms of naming in Swift, you should check out API Design Guidelines. These guidelines will give you a general feel of how to name things in Swift. Fair warning though, these rules are rather theoretical and at the end you are to decide how to name your functions in specific cases. Don't get too hung up on this really, even the most experienced developers have troubles with this, so I've been told.

In your particular situation you definitely shouldn't omit argument labels because type information is very generic and doesn't provide any clue as to what you're passing in.

Hope this helps!

Why Apple's closure declarations missing argument labels

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.

Extraneous argument label completion in call, swift 2

You can't use the data argument label because your argument label is not named data but is named eventArray. There's also an error in the CalendarController.fetchCalendarEvents call.

After fixes, your code should look like this:

func fetchCalendarEvents (completion: (eventArray: [Meeting]) -> Void) -> Void {

let eventStore : EKEventStore = EKEventStore()

eventStore.requestAccessToEntityType(EKEntityType.Event, completion: { granted, error in
if granted {
print("access granted: \(granted)")
completion(eventArray: arrayOfEvents)
} else {
print("error: access not granted \(error)")
completion(eventArray: [])
}
})
}

And:

let calController = CalendarController()
calController.fetchCalendarEvents { (eventArray) -> Void in
// ...
}


Related Topics



Leave a reply



Submit