Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the exclamation mark mean for a swift initializer?

I have seen code like this that XCode created from objective-c initializers:

init!(logMsg: String!, level logLevel: DDLogLevel, flag logFlag: DDLogFlag, context logContext: Int32, file: UnsafePointer<Int8>, function: UnsafePointer<Int8>, line: Int32, tag: AnyObject!, options optionsMask: DDLogMessageOptions)
init!(logMsg: String!, level logLevel: DDLogLevel, flag logFlag: DDLogFlag, context logContext: Int32, file: UnsafePointer<Int8>, function: UnsafePointer<Int8>, line: Int32, tag: AnyObject!, options optionsMask: DDLogMessageOptions, timestamp aTimestamp: NSDate!)

The original code is:

- (instancetype)initWithLogMsg:(NSString *)logMsg
                         level:(DDLogLevel)logLevel
                          flag:(DDLogFlag)logFlag
                       context:(int)logContext
                          file:(const char *)file
                      function:(const char *)function
                          line:(int)line
                           tag:(id)tag
                       options:(DDLogMessageOptions)optionsMask;
- (instancetype)initWithLogMsg:(NSString *)logMsg
                         level:(DDLogLevel)logLevel
                          flag:(DDLogFlag)logFlag
                       context:(int)logContext
                          file:(const char *)file
                      function:(const char *)function
                          line:(int)line
                           tag:(id)tag
                       options:(DDLogMessageOptions)optionsMask
                     timestamp:(NSDate *)aTimestamp;

What does the exclamation mark mean after the init keyword?

like image 272
Mike Lischke Avatar asked Oct 18 '14 13:10

Mike Lischke


People also ask

What does the exclamation mark mean in Swift?

The bang or exclamation mark hints at potential danger. If you use an exclamation mark in Swift, you are about to perform an operation that can backfire. You are about to perform a dangerous operation and are doing so at your own risk. That is the meaning of the exclamation mark in Swift.

What does exclamation point mean Xcode?

Swift uses exclamation marks to signal both force unwrapping of optionals and explicitly unwrapped optionals.

What is the exclamation mark?

The exclamation mark (!), known informally as a bang or a shriek, is used at the end of a sentence or a short phrase which expresses very strong feeling. Here are some examples: What a lovely view you have here! That's fantastic!

What are Initializers in Swift?

An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }


2 Answers

The currently accepted answer gives the what, but not the why. I think in this case, understanding why is especially important.

To answer your question directly, it's an initializer that returns an implicitly-unwrapped optional.

Using init? to indicate that initialization can fail is an effective way to handle errors. It returns an "optional" (such as Type?), implying that either a value was initialized, or nothing could be initialized and its contents are nil instead. But when would init!, which returns an implicitly-unwrapped optional, be useful?

Implicitly-unwrapped optionals indicate that you can be confident that the value you're currently working with is not nil without having to check it, but that it may have been nil at some point in its lifetime. This is in direct contrast to non-optional types, which can never be nil. Since you're working with a value from the very beginning of its lifetime when you obtain it from an initializer, there aren't many use cases for init!.

It likely exists primarily to help out with the Objective-C framework transitions to avoid having to manually check every single automatically-converted initializer. "This thing might be nil but probably isn't" is how Objective-C works by default. In your case, there's no way for Xcode to know whether or not those methods return an initialized value 100% of the time. It's quite an effort to go through every single framework and figure out whether an initialize should return a Type or Type?, so Type! is a sensible default in the meantime. As proof, Xcode is smart enough to convert initializers containing (NSError **) to init?.

One other use case is delegating to a failable initializer with one that you know will never cause the failure condition. But other than that, writing init! in your own Swift code should probably be avoided when possible (and even that case is still pretty iffy).

Sources:

  • Xcode release notes on the ongoing optional conformance conversion
  • This post on the Apple Developer Forums
  • My own thoughts on the matter
like image 75
Andrew Avatar answered Sep 29 '22 21:09

Andrew


It is failable initializer, introduced in Swift 1.1 (with Xcode 6.1)

From Apple Developer:

The init! Failable Initializer

You typically define a failable initializer that creates an optional instance of the appropriate type by placing a question mark after the init keyword (init?). Alternatively, you can define a failable initializer that creates an implicitly unwrapped optional instance of the appropriate type. Do this by placing an exclamation mark after the init keyword (init!) instead of a question mark.

You can delegate from init? to init! and vice versa, and you can override init? with init! and vice versa. You can also delegate from init to init!, although doing so will trigger an assertion if the init! initializer causes initialization to fail.

(emphasis mine)

like image 38
nicael Avatar answered Sep 29 '22 21:09

nicael