Reputation: 412
The Apple Swift Programming Language guide mentions the existence of the init! initializer, but does not provide any example for it. (Search for init! in this page)
I understand the use of a normal failable initializer declared with init?, but I fail to get the need of this other version. What is it needed for? Can somebody provide an example?
Upvotes: 6
Views: 1903
Reputation: 52592
It makes a difference in two situations:
If you write
let x: myclass = myclass(...)
then init? will not compile because init? returns an optional; init! will compile but crash if the init method returns nil.
If you write
let x = myclass(...)
then it will compile in either case, and it will not crash in either case. The difference is that in one case x has type myclass? and in the other case type myclass! with the obvious differences in behaviour.
If you write one of the following two:
let x: myclass? = myclass(...)
let x: myclass! = myclass(...)
then it doesn't matter whether init! or init? was used, because either can be assigned to an optional without crashing.
Upvotes: 1
Reputation: 17724
I'm going to take a stab at this even though this question has been around for a while because I think some example source code would be useful for understanding what init!
is for (at least it was for me).
An implicitly unwrapped optional provides two things of value:
?
' at the end of your optional variables), andnil
only once, and thereafter (as long as it is non-nil
) use its unwrapped (i.e. direct) value.The important part though is that an implicitly unwrapped optional is still an optional, which means it can be tested for nil
.
Now, as to the utility of the init!
-failable initializer, we can use it to get the two things I listed above (convenience and runtime efficiency), while still allowing an init
function to fail (i.e. to return nil
). This can happen, as others have noted, by calling into Objective-C API, but it can also happen directly from code you might choose to write. Here's an example:
class A {
init!() {
return nil // something happens that causes init to fail
}
}
var a:A! = A() // variable 'a' *is* an optional, and also nil
if a != nil { // and we can test it!
print( "a is not nil" )
} else {
print( "a is nil, better not use it." )
}
In this example, I gave myself a way to fail the initialization of class A
, and yes, could as easily have done it with an init?
method, but when I create an object of type A
I'll probably only ever need to test that the initialization succeeded or failed once--after all, I either created an A or I didn't--and afterwards if it's not nil
I'll just want to use the direct value. So in this case, using the init!
-failable initializer turns out to be pretty handy.
Upvotes: 1
Reputation: 987
Good question Matteo, I´m looking answer for the same question because init! don´t have sense (if it always init an object and we don´t need optional), but I haven´t found any clear answer.
I think that it´s because Apple haven´t finished his work: "...own Objective-C classes, and classes in frameworks that have not yet been audited, initializers are imported as init! ..."
Perhaps be util for you, the text in "Interacting with Objective-C APIs"(Apple)
Upvotes: 1
Reputation: 130122
I belive it's absolutely the same use of !
as in optionals. init?
will return an optional. init!
will return an implicitly unwrapped optional.
Implicitly unwrapped optionals are needed for calling Obj-C APIs where you are not sure whether it can return an optional or not. So you use an implicitly unwrapped optional and it behaves like a non-optional type but it will crash if an optional is returned.
Note that when Swift was introduced most Obj-C frameworks returned only implicitly unwrapped optionals but currently a lot of them return optionals or non-optional types because Apple is going through the code and checks whether they can return an optional or not. init!
is needed everywhere where Apple hasn't tagged the initializers correctly yet.
Upvotes: 2
Reputation: 2573
This serves two purposes:
When importing Cocoa APIs that Swift doesn't know about. If Swift does not know if an initializer can return nil or not, it annotates it with ! so that the developer knows there might be a nil hiding there, without forcing the dev to test for nil if there's actually no reason to.
For the same reasons implicitly-unwrapped optionals are used in other contexts (you may be willing to trade compile-time safety for added convenience in some cases).
Upvotes: 3
Reputation: 1
The init initializer is the same like the constructor for classes in other languages. It sets initial values and performs some initial Operations (like checking wether a value is to big etc.). Interesting: It also takes Parameters and can be overloaded.
Example:
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
So when when you call the struct it returns different values depending on your call parameters.
For more info: http://www.informit.com/articles/article.aspx?p=2246797
Upvotes: -3