9

As document said “you’re sure that the optional does contain a value, you can access its underlying value by adding an exclamation mark (!)

So why UIViewController init method use

init(nibName nibName: String!,bundle nibBundle: NSBundle!)

and tell me "If you specify nil, the nibName property is set to nil."

Why not use init(nibName nibName: String?,bundle nibBundle: NSBundle?) instead?

I am so confused about this.

Binarian
  • 12,296
  • 8
  • 53
  • 84
Wayne
  • 508
  • 5
  • 11
  • just call [aViewController alloc] init] if you don't have any Nib. – LE SANG Jun 03 '14 at 13:27
  • @iAn I just wonder why use ! not ? in swift – Wayne Jun 03 '14 at 13:29
  • possible duplicate of [Why create "Implicitly Unwrapped Optionals"?](http://stackoverflow.com/questions/24006975/why-create-implicitly-unwrapped-optionals) – Connor Pearson Jun 03 '14 at 13:41
  • @Wayne Its too early to say on swift, need to analyze and think of it. unnecessarily it will create more problems apart from original ;) – Madhu Jun 03 '14 at 13:48
  • perhaps it means you can just leave those arguments off if they're nil? Only pass nibName and nibBundle if they are non-nil. I.e. call as `init()` – nielsbot Jun 05 '14 at 00:43

4 Answers4

2

From my understanding ? is used to indicate an optional variable. ! is used to access the value of an optional variable. Document says

“Once you’re sure that the optional does contain a value, you can access its underlying value by adding an exclamation mark (!)”

That means use ! only if you are sure it has a non nil value otherwise it will throw error. Its like forcing an optional variable to have value.

Then about your question

init(nibName nibName: String!,bundle nibBundle: NSBundle!)

Here the init function is forcing the caller to pass the values for nibName and nibBundle. It cannot be nil. ! is used to make sure that the parameters has a non nil value

Note: If iam wrong please correct me, iam just learnig:)

Anil Varghese
  • 42,757
  • 9
  • 93
  • 110
  • Thanks for response, however, document allowed you pass nil to nibName and nibBundle, you can reference from Objective C init method, and also document said "If you specify nil, the nibName property is set to nil." – Wayne Jun 03 '14 at 13:48
  • What will happen if you pass nil as nibName? did you tried – Anil Varghese Jun 03 '14 at 14:00
  • you can build success : ) – Wayne Jun 03 '14 at 14:05
2

! is a pure syntactic sugar. The variable is still an optional; you can use it as a normal optional, passing nil, etc. It's only necessary so that you can simplify to nibName rather than use the full nibName!

Source—

“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.” ...

“An implicitly unwrapped optional is a normal optional behind the scenes, but can also be used like a nonoptional value, without the need to unwrap the optional value each time it is accessed. ”

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks

Community
  • 1
  • 1
ilya n.
  • 18,398
  • 15
  • 71
  • 89
1
init(nibName nibName: String!,bundle nibBundle: NSBundle!)

Is calling into Objective C framework code. This calls initWithNibName:bundle. You can optionally pass this method's arguments nil. Objective C is fine with that. If you pass nil in initiWithNibName it tries to resolve the name for you based on the name of the class in question. If you pass in nil for bundle it replaces this with [NSBundle mainBundle].

So, Swift makes this parameter an optional. It must do so to permit the variable to optionally be nil. The question is why does it not make it a standard optional and require you to explicitly unwrap it. The answer is that the implicitly unwrapped optional immediately unwraps the optional before passing it to Objective C. You don't want to have to explicitly unwrap this since once you pass your argument in, whether nil or otherwise, you are done setting it. You don't want to have to explicitly unwrap it and then pass it to Objective C! Doing so wouldn't make any sense.

SmileBot
  • 19,393
  • 7
  • 65
  • 62
  • So actually having the ! in the parameter type allows you to pass a nil, an NSBundle? and an NSBundle right? – Nicolas Manzini Jun 19 '14 at 19:24
  • @NicolasManzini Hi, yes. You can pass in nil. If you do, it gets replaced by the framework. In the case of the nibName it gets replaced by the associated viewController's name using various ways of truncated the name. In the case of NSBundle it gets replaced by [NSBundle mainBundle] on the objc side. If there is no Class corresponding to the name, in the former case, an error is thrown. Does that answer the question? – SmileBot Jun 20 '14 at 18:22
  • Your code is not 'calling into Objective C code'; your code is a function interface declaration. – GoZoner Nov 07 '14 at 06:00
0

I found the following on this Site

In some cases, you might be absolutely certain that an Objective-C method or property never returns a nil object reference. To make objects in this special scenario more convenient to work with, Swift imports object types as implicitly unwrapped optionals. Implicitly unwrapped optional types include all of the safety features of optional types. In addition, you can access the value directly without checking for nil or unwrapping it yourself. When you access the value in this kind of optional type without safely unwrapping it first, the implicitly unwrapped optional checks whether the value is missing. If the value is missing, a runtime error occurs. As a result, you should always check and unwrap an implicitly unwrapped optional yourself, unless you are sure that the value cannot be missing.

I'm not sure yet if this makes sense.

dasdom
  • 13,975
  • 2
  • 47
  • 58