In a Swift function signature, what does the !
after an argument imply? More specifically, does it mean the argument needs to be unwrapped before it is passed in or that it gets unwrapped (automatically) as it is passed in. Here is an example:
func annotationButtonTUI(sender: UIButton!) { }
In this case the function is a target for a UIButton so whatever happens with the !
is happening automatically.
My thought is it means you can expect an unwrapped sender
object so you don't need to try an unwrap it.
A : in the function signature always means an input argument to the function. The function signature contains the argument label followed by a : . The _ means there's no argument label, in which case you can omit the : as well when supplying that specific input argument to the function call.
In Swift, the underscore operator (_) represents an unnamed parameter/label. In for loops, using the underscore looping parameter is practical if you do not need the looping parameter in the loop.
All of this information is rolled up into the function's definition, which is prefixed with the func keyword. You indicate the function's return type with the return arrow -> (a hyphen followed by a right angle bracket), which is followed by the name of the type to return.
This isn't quite a duplicate — there's some subtlety to implicitly unwrapped optionals in function signatures beyond their usage elsewhere.
You see implicitly unwrapped optionals in API imported from ObjC because that's the closest Swift approximation of an object that's expected to be there but which can be nil. It's a compromise for imported API — you can address these variables directly like in ObjC, and you can test them for nil using Swift optional syntax. (There's more about Apple's rationale for this in the Advanced Interoperability talk from WWDC14.) This pattern also applies to the IBAction
declarations inserted by Interface Builder, since those methods are in effect getting called from ObjC code, too.
As you seem to have suspected, Swift wraps the possible nil in an optional when bridging from ObjC, but the !
in your function implementation's declaration unwraps the value so you can use it directly. (At your own risk.)
Since Swift 1.2 (Xcode 6.2 in Spring 2015), ObjC APIs can be annotated with nonnull
and nullable
, in which case the Swift interface to those APIs uses either a non-optional type or a fully optional type. (And since Swift 2.0 / Xcode 7.0, nearly all of Apple's APIs are audited to use nullability annotations, so their Swift signatures don't use much !
anymore.)
What's less well-known about this is that you're free to change the optionality of parameters when you implement your own Swift functions that get called by ObjC. If you want the compiler to enforce that sender
in your action method can never be nil, you can take the !
off the parameter type. If you want the compiler to make sure you always test the parameter, change the !
to a ?
.
The exclamation point after type declaration in the Swift method signatures means the parameter is an Implicitly Unwrapped Optional. That means it is an Optional type (that would be normally denoted with ?
after the type) that gets unwrapped every time you access it in the method body. Not as it is passed in. It is as if you used forced unwrapping — sender!.titleLabel
— each time you use it, but you do not have to type the exclamation point every time — hence implicitly unwrapped optional.
From Using Swift with Cocoa and Objective-C, section Working with nil:
Because Objective-C does not make any guarantees that an object is non-nil, Swift makes all classes in argument types and return types optional in imported Objective-C APIs. Before you use an Objective-C object, you should check to ensure that it is not missing.
Implicitly unwrapped optional allows you to treat it in the Swift code like a normal value type with the caveat that accessing it when it is nil
will interrupt your program with runtime error. You’d guard against that using if statements, optional binding or optional chaining.
Implicitly unwrapped optionals are pragmatic compromise to make the work in hybrid environment that has to interoperate with existing Cocoa frameworks and their conventions more pleasant, while also allowing for stepwise migration into safer programing paradigm — without null pointers — enforced by the Swift compiler. You’ll meet them all over Cocoa APIs, but there are also some use cases for them in pure Swift as discussed in Why create "Implicitly Unwrapped Optionals"?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With