14

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?

Mike Lischke
  • 48,925
  • 16
  • 119
  • 181
  • I added an answer here that may be useful: http://stackoverflow.com/a/31422223/312594 – par Jul 15 '15 at 05:36

3 Answers3

19

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:

Andrew
  • 2,438
  • 1
  • 19
  • 19
  • 1
    Thanks Andrew, however the question was about the what not the why. As soon as I know what it is I can easily find the documentation for it. – Mike Lischke Oct 27 '14 at 10:25
  • 1
    I understand :). I'm just hoping to shed some insight that can't be found in the documentation to people that may come across this. I feel it's important in this case. – Andrew Oct 27 '14 at 13:24
  • You said, "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!." I disagree with this. There are plenty of times when you, the programmer, know that the init will succeed (`UIImage(named:)` for example) but the compiler doesn't. Use of `!` in those contexts is completely appropriate. – Daniel T. Nov 02 '14 at 14:05
  • I see what you mean, it's definitely appropriate to force-unwrap an `init?` initializer that's non-nil the first time and every time thereafter. I'm talking specifically about implicitly unwrapped optional failable initializers—`init!`. `UIImage(named:)` is an `init?` initializer for the very reason you mentioned, that the compiler doesn't know it'll succeed. Interesting distinction! – Andrew Nov 02 '14 at 15:12
  • @Andrew's answer is the complete, easy to understand solution. Good job – Cristi Habliuc May 20 '17 at 13:11
14

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)

nicael
  • 18,550
  • 13
  • 57
  • 90
1

These are called 'Implictly Unwrapped Optionals'[1]. The obj-c type for logMsg (for example) is NSString*, which can be nil. It could be used as an optional - String?, in which case you would to explictly unwrap it to get the value. String! will give you the value directly, so this assumes that logMsg won't be nil.

These kinds of optionals are defined as implicitly unwrapped optionals. You write an implicitly unwrapped optional by placing an exclamation mark (String!) rather than a question mark (String?) after the type that you want to make optional.

Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter.

--
1. https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html

radical
  • 4,364
  • 2
  • 25
  • 27
  • 2
    Oh, I misunderstood your question and missed the 'init!' part :/ nicael's answer explains that. – radical Oct 18 '14 at 14:08