I am using playground to run the below code
var a : Int!
a = nil
print(a) o/p - none
print(a!) o/p - crash
a = 5
print(a) o/p - some(5)
print(a!) o/p - 5
I know optionals is enum and it has two type none or some.
But as I am declaring a as implicitly unwrapped I think I don't have to unwrap it to get the actual data.
Whether I have understood optionals wrong ?
As others have said, IUOs (implicitly unwrapped optionals) are now regular optionals with some hints to the compiler that gives it permission to unwrap them.
That being said, print is handled differently. Try using an assignment to a non-optional variable instead. That's a better test, e.g:
var a : Int! = nil
let b: Int = a
Here’s a use case for implicitly unwrapped optionals. In any class, all properties have to be initialised upon initialisation of the class instance. You can either assign the properties a default value or use the init function for property initialisation.
In a view controller, however, you don’t want to use an init function. Some properties might not have default values but will rather be initialised during viewDidLoad. In this case you could declare the property as implicitly unwrapped because it won’t be accessed before view controller loading—and after that you can make sure in viewDidLoad (or in the calling view controller’s prepareForSegue method, for example) that it is not nil, hence safe to be accessed from now on.
Just my two cents to add to your understanding of IUOs.
Related
This question already has answers here:
Swift variable decorations with "?" (question mark) and "!" (exclamation mark)
(1 answer)
What is the difference between String? and String! (two ways of creating an optional variable)?
(7 answers)
Closed 4 years ago.
I noticed that some coding examples for Swift declare optional properties in different ways. However, I seem to have trouble trying to tell them apart (or, rather, when to use each.)
class MyClass {
// I believe this can start as nil but should always be set
// once it is.
var optionalProperty1: Type!
// I believe this can be set or nil anytime.
var optionalProperty2: Type?
// I think this is the same as
// var optionalProperty3: Type!
lazy var optionalProperty3: Type
}
How does each one differ from the others and when should each one be used?
var optionalProperty1: Type!
When you're sure you will have value for this property such as timestamp it will be something for sure. And Yes it can be nil too.
var optionalProperty2: Type?
When you're not sure about the value (Or this field is not mandatory) take it as optional for example:- If I make a Person class address can be optional and name will not.
lazy var optionalProperty3: Type
This syntax is wrong you can not declare lazy property in this way. You must assign something to it initially. See below example:
/// First way
lazy var optionalProperty3: String = {
return "Hello"
}()
/// Second way
lazy var optionalProperty4 = "Hello"
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration. lazy variables are great for things that need to be setup once, then never re-set.
One more thing you really don't need to specify type in modern Swift. Means if you will assign 0 it will be an integer itself, if you will assign 0.0 it will take it as double and same for String, Array etc.
The third declaration is not an optional.
The third one declares a lazy property. Lazy properties will only be initialised when they are first used. Example:
class A {
lazy var a: Int = {
print("hello")
return 1 + 1
}()
}
let a = A()
print(a.a)
If you remove the last line, hello will not be printed.
The first declaration is a implicitly unwrapped optional while the second declaration is a normal optional.
When you access members of a normal optional, you need to unwrap it with ? or !:
var myInt: Int? = ...
print(myInt.description) // doesn't compile, must unwrap
print(myInt!.description) // will crash if myInt is nil
print(myInt?.description) // will print "nil" if myInt is nil
On the other hand, implicitly unwrapped optionals do this implicitly - whenever you try to access a member, it will implicitly unwrap it with ! for you:
var myInt: Int! = ...
print(myInt.description) // equivalent to "myInt!.description"
From Apple's Swift documentation:
Optionals (?): "You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn’t a value at all."
Implicitly Unwrapped Optionals (!): "As described above, optionals indicate that a constant or variable is allowed to have “no value”. Optionals can be checked with an if statement to see if a value exists, and can be conditionally unwrapped with optional binding to access the optional’s value if it does exist.
Sometimes it’s clear from a program’s structure that an optional will always have a value, after that value is first set. In these cases, it’s useful to remove the need to check and unwrap the optional’s value every time it’s accessed, because it can be safely assumed to have a value all of the time.
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. The primary use of implicitly unwrapped optionals in Swift is during class initialization, as described in Unowned References and Implicitly Unwrapped Optional Properties."
Read more at https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html
Explicitly Unwrapped Variable
var optionalProperty1: Type!
This means that the value should never be nil. It will always be initialized but it is better to use var optionalProperty1: Type
Optional
var optionalProperty2: Type?
This is an optional value, meaning that it can either have a value or be nil. normally to use the value you would need to unwrap it. using either conditional unwrapping or a guard statement...
if let value = optionalProperty2 {
print("optionalProperty2 had a value, value is set")
}
guard let value = optionalProperty2 else {
print("optionalProperty2 was nil value is nil")
}
or you can just check if it has a value and explicitly unwrap it (which is not considered best practice)
if optionalProperty2 != nil {
print("optionalProperty2 is set to \(optionalProperty2!)")
}
Lazy Variable
lazy var optionalProperty3: Type a lazy variable is different, it is not an optional unless you define it to be optional. Lazy variables do not initialise to a value until the value is first used. So if you do not call/use the variable it will never be set.
In Swift 2.2, I often declared variables using a concise syntax similar to let x = UIView?(). This gave x the UIView? type, and initialised it with nil. (Of course, you could use any type instead of UIView in these examples)
However, when I do the same in Swift 3.0, I get an error:
Cannot invoke initializer for type 'UIView?' with no arguments. It also says that Overloads for 'UIView?' exist with these partially matching parameter lists: (Wrapped), (nilLiteral: ()). Somehow, I don't think UIView?(nilLiteral: ()) is quite what I'm after.
Naturally, there are other alternative methods to do the same thing, such as let x: UIView? = nil and let x = nil as UIView(), but they're more verbose than the method I was using previously. Was the UIView?() constructor removed in Swift 3.0, or has it been replaced in a form that I've not yet discovered?
The following does initialise x to nil, the brackets are entirely superfluous.
var x: UIView?
return x == nil
Will return true
Check out the developer docs for more information.
https://developer.apple.com/library/content//documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html
If you define an optional variable without providing a default value,
the variable is automatically set to nil for you:
var surveyAnswer: String?
// surveyAnswer is automatically set to nil
#Hamish posted a comment to clarify the reason why UIView?() no longer works:
“The syntax UIView? is just syntactic sugar for Optional, therefore UIView?() is just syntactic sugar for Optional.init(). In Swift 2, Optional's init() constructs a new optional value set to .None. So yes, it was working correctly. In Swift 3 however, this initialiser has been removed, which is why UIView?() no longer works”
I have a string var oneString: String! and later on in a method, when I want to concatenate a string to oneString I have to do this:
oneString! += anyString
If I don't add ! I get an error 'String!' is not identical to 'CGFloat'
If I initialize my string with var oneString = "" I don't have this problem. Why? Why do I need to unwrap oneString while I explicitly said it would not be nil when I declared it?
Why do I need to unwrap oneString while I explicitly said it would not be nil when I declared it?
You’ve misunderstood what var oneString: String! means. It does not mean oneString will not be nil. If you declare a type as var oneString: String, then you are declaring a type that cannot be nil.
The type String! is an “implicitly-unwrapped optional”. That is, it’s an optional, much like String?, but one that pretends to be a non-optional sometimes. Mostly for the purposes of reading it – you don’t have to explicitly unwrap it to get the value out. The downside being, if it is ever nil (and it totally can be), your code will trap and abort.
But this pretending-to-not-be-optional only goes so far. You cannot pass a String! to a function as inout when that argument is not an optional. Hence your problem.
Anton’s answer is completely correct in why it won’t work, and his suggested operator overload will make your code compile. But it isn’t the right solution – you should instead avoid using implicitly-unwrapped optionals as they are spring-loaded deathtraps and only to be used in specific circumstances (the most common being with Cocoa UI controls). 999 times out of 1,000 you would be better off with a regular optional or non-optional
Reason is that Foo, Foo? and Foo! are different types in Swift.
There are certain operators pre-defined for you "out-of-the-box" which allow great deal of transparency between Foo and Foo!, but still these types are not the same.
When it comes to strings, operator
func += (inout left: String!, right: String)
... is simply not defined.
If you declare it like:
func += (inout left: String!, right: String) {
left = left + right
}
... then your code should compile the way you like it, that is:
oneString! += anyString
I was under the impression that implicitly unwrapped optional will cause a runtime exception when used and it is nil. But the following code works without runtime exception, why?
var str:String?
println(str!) // Crashes as expected
var str:String! // Implicitly unwrapped
println(str) // Does not crash, not what I expect - it prints nil
It prints the variable as enum (i.e. optional), because internally an optional is enum Optional<T>.
More precisely, I presume it uses the debugDescription property, in fact this is what happens:
var str:String?
println(str) // Prints "nil"
str.debugDescription // Prints "nil"
An implicitly-unwrapped optional is only forcibly unwrapped in a situation which expects a non-optional. println() accepts all types, including optionals, and so there is no need to forcibly unwrap it before passing to println(). Since it is not unwrapped, it does not crash.
The name of the ! always confuses me: it's called an 'implicitly unwrapped optional'. However, what is implicit about it? Implicit means "implied though not plainly expressed." However, does not adding a ! plainly express its purpose? Does not adding a ! make it explicit what we are trying to accomplish?
In Swift, trailing exclamation marks (!) are used in two different ways. One is called Forced Unwrapping. This is when you have a variable defined as an Optional and you want to basically assert that the value is not nil so that you can use it as if it were not an optional:
var optionalName: String? = "World"
if optionalName != nil {
sayHelloTo(optionalString!)
}
An alternate way you could describe "Forced Unwrapping" is "Explicit Unwrapping", but forced adds the extra hint that the whole program will crash if you try to "Force Unwrap" an optional that is nil.
The second is when you are actually declaring the type of a variable and it is called an Implicitly Unwrapped Optional. This is for when you want to declare a variable that is technically optional, but that you will treat as if it is not optional. Every time you use this Implicitly Unwrapped Optional, it is in reality, doing the "Force Unwrapping" I described above:
var name: String! = "World"
if name != nil {
sayHelloTo(name)
}
You can still test an Implicitly Unwrapped Optional for nil, but you can also use it directly as if it were not optional. That is why it is considered implicit. Every time you use it, it is automatically, implicitly unwrapped for you.
Like "Forced Unwrapping" an "Implicitly Unwrapped Optional" will still crash the entire program if you try to use it when it is nil
Normal Optional
var foo : Foo? = Foo()
foo!.doSomething() // explicitly unwrap it and call the method
Implicitly Unwrapped Optional
var foo : Foo! = Foo()
foo.doSomething() // implicitly unwrap it and call the method just like it is not optional
In both case, you need something to declare an optional (? or !). Implicitly Unwrapped Optional does not add more. But you can omit unwrap operator when use it.