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
How to Use Nsurlsessiondatatask in Swift
-[Uiapplication Delegate] Must Be Called from Main Thread Only
Nsmutableurlrequest Timeout Interval Not Taken into Consideration for Post Requests
Add Child View Controller to Current View Controller
Uicollectionview Adding Image to a Cell
How to Add iPhone 5 Large Screen Support to iOS Apps in Xcode
Dtassetproviderservice Could Not Start Dtxconnection with Simulator
Differencebetween a Property and a Variable in Swift
Exc_Bad_Access When Building Nspredicate
What Is Export * in Module.Modulemap File Inside Each Framework
iOS - Mkmapview Place Annotation by Using Address Instead of Lat/Long
Does @Synchronized Guarantees for Thread Safety or Not
How to Check If the iOS Device Is Locked/Unlocked