Swift optionals, unwrapping - ios

I am learning the swift syntax and got a little confused with the optional type.
So, from the defination a swift type can not store the null value unless it is explicitly defined as an optional. So, what does the variable in the following line contains when it's declared.
var a:Int (declaring a variable without intializing it working fine in swift 3)
And also when we declare a variable as an optional with a "!",
var optionalSquare: Square! = Square(sideLength: 10, name: "Optional Square")
if we want to use the "optionalSquare" variable, we do not need to unwrap it cause we are sure(I think that is why we are using "!" instead of "?") it does not contain any null value. so why don't we declare it as a normal variable.
Please correct any false statements. Thank you.

what does [var a:Int] contains when it's declared
Nothing. Its value is undefined. Using it before assigning a value is a compilation error. You can declare it without initializing it, but you cannot use it.
This is part and parcel of Swift's philosophy of safety: in C, you could likewise leave a variable uninitialized, and its value would be undefined, but the compiler would not (by default) report error if you use it.
so why don't we declare it as a normal variable.
There's no reason that I can think of to make a local variable an implicitly unwrapped optional. The functionality is intended for properties ("ivars") on structs or classes. You should use them where it's impossible to set the property in the object's init, but it is certain that the value will be present before the object is used.
IBOutlets are probably the canonical use case. Another use that I find helpful is to allow setting a property by calling a method in init.

So, what does the variable in the following line contains when it's declared.
It does not matter, because you cannot access it anyway. A declaration like this tells Swift that you are going to decide on the value later. Reading the variable before assigning is an error that the compiler is going to catch.
why don't we declare [variables with forced unwrapping] it as a normal variables?
Because you may want to store nil in that variable at the times when it should not be used.
For example, you should make IB-assigned property implicitly unwrapped, because they need to be nil before NIB objects are "inflated", but after the init method has completed:
#IBOutlet private weak var myLabel: UILabel!
In order to make myLabel non-optional you would have to drop weak. On the other hand, you don't want to use exclamation point on each access of myLabel, because you know for sure that it must be initialized.
The same reasoning applies to other variables that you would like to make non-optional, but cannot assign in an initializer.

You can declare a non optional variable and not initialize it - the compiler doesn't complain as long as you do not use that variable. So this code
var num: Int
won't generate any error. However if you reference that variable before initializing, compilation fails
var num: Int
print(num)
In the former case there's no error because initialization can be deferred. You can declare a variable, and then initialize 100 lines after. As long as you don't reference it before initializing, you're ok.
To answer your second question, it's correct to say that in many cases it doesn't make much sense declaring and contextually initializing an implicitly unwrapped variable: a non optional variable is more appropriate.

Related

When to use ?, !, None, or Lazy?

I just started learning Swift and recently found out about
"Normal" variables (for lack of a better name):
ex: var test1: String
"Optional" variables
ex: var test2: String?
"Implicitly Unwrapped Optionals"
ex: var test3: String!
Lazy variables
ex: lazy var test4: String
My understanding is this:
Use "Optional" variables (?) when the variable may or may not be initialized at points in the future starting from initialization
Use "Implicitly Unwrapped Optionals" (!) when the variable is guaranteed to be initialized
Optionals can be converted to Implicitly Unwrapped Optionals via "Forced Unwrapping"
ex: let possibleString: String? = "Hello"
println(possibleString!)
Use "Lazy variables" when there is no need for something to be set until initialization (it seems these can be used with (?) or (!))
Therefore, my questions are:
When do I use option 1 - a variable without ? and without !
When do I use "lazy"
I read "lazy" is often used for singletons - why?
I have the most experience in Java and C++ terms, if that helps with my background for answering.
Edit: Here's everything I found (The main issue was "Normal" vs "Implicitly Unwrapped Optionals":
"Normal" variables must be initialized: (a) On the same line, (b) in the same scope before usage (Usage means some operation with the object), (c) by the end of the init iff the variable is a field. Note: The scope of init is everything in the scope of the class AND not in the scope of functions within the class.
Printing an Implicitly Unwrapped Optional will print "nil", but using the variable's functions will throw a runtime exception. Meanwhile, using (at all, including print) a Normal variable will not allow the program to compile at all
The purpose of using ! over "" (Nothing) is (a) More leniency since the program will compile (and run correctly given the variable is actually initialized) and (b) Lets you not initialize everything at the very beginning. Note: It is a compile time error to have any field undeclared if it is a Normal variable.
Not exactly that.
All variables must be initialised before the first use, and all class/struct stored properties must be assigned value in respective initialiser. Optionals are not about being allowed uninitalised at some point, but about being allowed to contain no value, which is represented by nil, which is still perfectly an initialised stated for such variable. Therefore, if something can not be known at the moment of initialisation then that's probably where you will use some sort of an optional (e.g. delegate for a view).
Implicitly unwrapped optionals is a sort of shorthand for cases when a variable might be empty, but we are absolutely sure that when we will be really using it it will hold an actual value (typical example is a property in a view controller that holds reference to a view).
Forced unwrapping does not convert optional into implicitly unwrapped optional, instead it gives you a value that is there if it's there (i.e. if optional is not nil), and throws an exception if it's not.
Lazy properties are used in cases when you want to defer their initialisation to a later stage, when the property is actually being used for first time. Usual case is if you need to access an expensive resource to do that (load huge file from disk, download it via network, etc), especially so if there might be cases when such property is not going to be used at all (why loading it from the disk if we will not use it probably?).
let's see Apple's example
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
Residence instances have a single Int property called numberOfRooms, with a default value of 1. Person instances have an optional residence property of type Residence?.
If you create a new Person instance, its residence property is default initialized to nil, by virtue of being optional.
1. If you need default value for property to be nil - use optional. Using variable without ? and ! - like 'numberOfRooms' -
You can set the initial value of a stored property from within an initializer, as shown above. Alternatively, specify a default property value as part of the property’s declaration. You specify a default property value by assigning an initial value to the property when it is defined.
NOTE
If a property always takes the same initial value, provide a default
value rather than setting a value within an initializer. The end
result is the same, but the default value ties the property’s
initialization more closely to its declaration. It makes for shorter,
clearer initializers and enables you to infer the type of the property
from its default value. The default value also makes it easier for you
to take advantage of default initializers and initializer inheritance.
2. ! is used to access the value wrapped inside variable when it is not nil, and throws exeption otherwise. So, you can use ! in order to make mark for users of you class - 'this value will not be nil at the time you unwrap it'
3. Lazy variable is used when you want to init it later, not at the time of whole object creation but exactly at the time you ask getter for data. this is useful when property stores an array, for example:
lazy var players: [String] = {
var temporaryPlayers = [String]()
temporaryPlayers.append("John Doe")
return temporaryPlayers
}()
When should I use lazy initialization?
One example of when to use lazy initialization is when the initial value for a property is not known until after the object is initialized.
Short explanation:
A non optional variable has always a value and can never be nil.
The variable must be initialized in the init method or in the declaration line.
var a : String
var b = "bar"
init {
a = "foo"
}
An implicit unwrapped optional variable must not be initialized in the init method
or in the declaration line but is guaranteed to have always a value when it's used
var a : String!
func viewDidLoad() {
a = "Hello"
a += " world!"
}
An optional variable may have a value and is nil at declaration
var a : String? // = nil
A lazy variable is initialized later at the moment it's used the first time
class foo {
lazy var bar : String = {
return "Hello"
}()
}

What is the difference between 'var contacts = [details]()' and 'var contacts:[details]?' in ios swift

I wrote my code using var contacts:[details]? = nil and I was facing problems like I could not access contacts?.count and I had to use optionals everywhere.
For e.g contacts[indexPath.row]?.firstname
But when I use var contacts = [details]() I do not have to use to optionals anywhere. I can directly use contacts.count and contacts[indexPath.row].firstname
What difference is there between the above two that we don't need to use ? anymore even when the array is empty
Moreover using var contacts:[details]? was not working for me.
First one initialises an array(of type details) and gives you an empty array while the second one just declares a variable (optional) which can be of details type
Optionals
var contacts : details?
is an optional variable (which can be of type details when not 'nil')
So whenever you are trying to access an optional variable, Swift is using optional chaining and you have to put ?
EDIT
I am not understanding where do we put ? and where do we not put it
From Swift's Doc
You specify optional chaining by placing a question mark (?) after the optional value on which you wish to call a property, method or subscript if the optional is non-nil. This is very similar to placing an exclamation mark (!) after an optional value to force the unwrapping of its value. The main difference is that optional chaining fails gracefully when the optional is nil, whereas forced unwrapping triggers a runtime error when the optional is nil.
So you put ? when you want to unwrap the variable and call a property on it.

Issues setting string to optional value

how can i pass the label inside the button to the next activity,
here is my code but it doesn't work
#IBOutlet weak var elecB: UIButton!
my prepareForSegue code
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var result:searchResultView = segue.destinationViewController as! searchResultView
if elecB.selected{
result.cat = elecB.titleLabel?.text!
}
}
it tells me there is an error in this line of code
result.cat = elecB.titleLabel?.text!
cat is a string
can any one help me, all i want to do is pass the label inside the button clicked to the next view controller
Change the declaration of titleLabel to titleLabel: UILabel! or titleLabel: UILabel, since you don't actually need it to be optional. It sounds like you'd reasonably expect for that label to exist all the time.
Making cat optional is also not the best solution, since you expect that string to always have a value. So leave cat as is, and make your title label non-optional, or implicitly unwrapped (!) if Xcode complains.
What do ? and ! mean?
A ? after a declaration means that that variable is optional, and can be reasonably excepted to be nil (this also allows you to set it to nil). You also have to follow the variable name with a ? every time you want to use it, or wrap it in an if let a = myOptionalVar {...}, so that code will only execute if the variable is not nil.
A ! after a declaration makes it an implicitly-unwrapped optional. This means that the variable can be nil, but is assumed to not be nil in most circumstances, so you don't have to follow it with an ! every time you want to use it. Note however, if the variable does happen to be nil when you try to use it, your program will crash.
! should only be used when you absolutely have to, because it is unsafe by nature. For example, if Interface Builder requires #IBOutlet variables to be optional, it is best to make them !, because they will be automatically initialised when your class is created from the storyboard, and will have a value for the rest of the time.
Using neither of these means that the variable is not optional, i.e. it must always have a value, and cannot be nil.
Check out the Swift documentation for the definition of optional variables (the ones with the ? at the end of the declaration.
If you define a variable like this var cat:String? then the variable is optional. That essentially means that the variable can have nil as a value.
From Apple's documentation:
You use optionals in situations where a value may be absent. An optional says:
- There is a value, and it equals x
or
- There isn’t a value at all
The example below uses the toInt() method to try to convert a String into an Int:
let possibleNumber = "123"
let convertedNumber = possibleNumber.toInt()
// convertedNumber is inferred to be of type "Int?", or "optional Int"
Because the toInt() method might fail, it returns an optional Int, rather than an Int. An optional Int is written as Int?, not Int. The question mark indicates that the value it contains is optional, meaning that it might contain some Int value, or it might contain no value at all. (It can’t contain anything else, such as a Bool value or a String value. It’s either an Int, or it’s nothing at all.)

Are class-based Swift Constants Forced to be Optional

I'm very new to Swift development, so apologise if this is a really silly question - having read Apple's guide, I am surprised by the behaviour I have come across (and a little miffed).
I am creating a really simple class which defines a number of uninitialised constants at the beginning of the class. When the class is initialised, the values are set. It seems as though I cannot do this unless I declare the constants to be optional, even though they are not optional and are all set in the constructor. For example:
class TestClass {
private let urlAddress:String
init(urlAddress: String) {
self.urlAddress = getUrlAddressWithProto("http", urlAddress:urlAddress)
}
func getUrlAddressWithProto(proto: String, urlAddress:String) -> String {
return "\(proto)://\(urlAddress)/"
}
}
The function getUrlAddressWithProto returns a non-optional String but Xcode throws the error:
error: variable 'self.urlAddress' used before being initialized
Does anyone have any thoughts firstly on why this is the case and if there is a suitable alternative to declaring all my constants as optional?
The compiler probably wants to tell you that you are not allowed to call that function before all non-optional variables are initialized. Sometimes the error messages are not very obvious.
Swift prevents the use of instances that are in an inconsistent state. Swift does not know that the function you call doesn't rely on internal state, so you can't call instance functions before init is done at all.
You have a couple of options, besides marking the variable as optional.
Turn that function into a class function. Since class functions are not bound to an instance you can call them before the init of the instance is done
move the code from the function to the initializer
Turn the variable into an implicitly unwrapped optional. (i.e. let urlAddress: String!). You can use that variable as if it were a non-optional variable. Just make sure that you set it during init. If you do something with it while it is nil the program will abort.
Depending on your real code the last one is probably the only viable option.

Semantics between optional and non-optional function parameters in Swift and best use cases

I've seen a lot of discussion regarding variables in Swift that are declared as var a: String? and var a: String! the former being an optional variable of type String and the latter being implicitly unwrapped optional String. From my understanding, when something is implicitly unwrapped there's an assumption being made that there's a value already included in the optional value. In order to use the syntax a!.toInt() there would have to be an outside check like so:
if a != nil {
a!.toInt()
}
As a side note, it seems better practice to just declare variables as an optional type and then use optional chaining to unwrap the value if it exists. Doing:
if let numberString = a?.toInt() {
numberString.toInt()
}
Is there a scenario in where accessing a variable like a!.toInt() should ever be used in practical applications? To me, it seems like you'd be asking for runtime errors.
Now for the actual question. I was looking through the documentation, specifically enumerateObjectsUsingBlock on NSArray and the block parameter is declared using an !. Does this mean that the writers of that function are assuming that the block parameter will be non-nil? If so, inside that function, what is the semantic difference between:
func someMethodWithBlock(block:((String!)-> Void)!) {
var a = "Hello"
block.(a) //first syntax example
block?.(a)//2nd
block!.(a)//3rd
}
Implicitly Unwrapped Optionals are used almost everywhere in the Cocoa APIs as they are imported into Swift — this is to maintain compatibility with the kind of pointer semantics that are ubiquitous in Obj-C, without requiring !s and ?s all over the place. That's why the NSArray method's block takes a String! argument.
In Swift, regular Optionals (Int?, etc.) are largely preferable for the reasons you specified: they are less prone to errors. Implicitly Unwrapped Optionals are mostly meant to be used only in certain cases, like when you need to pass self to a function before initialization is complete. (If you know a variable is not nil, unwrapping it like a!.toInt() is just fine. The danger with IUOs is that it would be written a.toInt(), and to a reader this looks completely safe, when in reality it's not.)

Resources