Swift optionals confusion - swift

I'm having a bit of a hard time wrapping my head around optionals and why they are beneficial.
First off, are these two code block essentially equivalent?
Swift:
if let unwrappedName = p.name {
var greeting = “Hello “ + unwrappedName
} else {
var greeting = “Hello stranger”
}
Objective-C:
NSString *greeting;
if (p.name) {
greeting = [NSString stringWithFormat:#"Hello %#", p.name];
} else {
greeting = #"Hello stranger"
}
Second, this is coming from the Swift iBook, I don't get any errors on these but what exactly is the difference between them??
1.
let optionalSquare: Square? = Square(sideLength: 10, name: "Optional Square")
let sideLength = optionalSquare?.numberOfSides
2.
let optionalSquare: Square! = Square(sideLength: 10, name: "Optional Square")
let sideLength = optionalSquare?.numberOfSides
3.
let optionalSquare: Square? = Square(sideLength: 10, name: "Optional Square")
let sideLength = optionalSquare!.numberOfSides

Yes, optional types are pretty similar for reference types to Objective-C references. The key difference is that non optional type can never be "nil". If the type of returned a method you are calling is Object?, you are forced to unwrap it before using it. It is clear that the response can be "empty" and the compiler will force you to handle that.
If the type is not optional then you never need to check if it is nil before using. In addition, Optional work with value types like Int. You don't need to remember if the empty value is 0 or -1 or some other magic value.
You should use optional pretty much anytime you are thinking about using a magic sentinel value that means the absence of something, ie 0, -1, nil, empty list, empty string, etc. It not hard to remember what should be checked but it is easy to forget. With optional, you do not need to "double check" its not nil, even though it "should not be nil but maybe it is". Instead, of return -1 as an index of an object that was not found return Int?. Instead of throwing an exception, when a file is not found you can pass a an optional object.
Compare with optionals:
if let mapleSyrup = shoppingList.removeAtIndex(3) {
print "Bought /(mapleSyrup)"
}
To without optionals and not perfectly clear documentation:
var mapleSyrup = shoppingList.removeAtIndex(3)
if mapleSyrup != nil && mapleSyrup.isEmpty {
print "Bought /(mapleSyrup)"
}
The second question is answered well in the swift ibook here.
let optionalSquare: Square! = Square(sideLength: 10, name: "Optional Square")
Lets you use optionalSquare as if it was a normal variable and doesn't need to be unwrapped first.
let sideLength = optionalSquare!.numberOfSides
If you know optionalSquare has a value, you can force to be unwrapped and used with !.
This article starts with some great information on the problems with nil and the benefits of optional types.

Related

I don't want to 'unwrap' an NSNumber - Swift

What an utter nightmare this portion of Swift seems to be...
let priceNumber = dictionary[kSomeKey] as? NSNumber
cell.titleLabel.text = String(format: "The price is £%li",priceNumber?.longValue)
Compile error: value of optional NSNumber not unwrapped
Now, forgive me for potentially being a complete cretin, but I just want my old Obj-C style if nil, display 0... what on earth is going on? if this dictionary key is nil, putting the suggested (priceNumber?.longValue)! will crash right?
Closest approach
let priceNumber = dictionary[kSomeKey] as Int? ?? 0
cell.titleLabel.text = "The price is £\(priceNumber)"
The nil coalescing operator ?? unwraps the optional if it's not nil
I'll try this way:
%li is expecting a long integer.
In Swift nil is not the equivalent of zero like it might happen in some cases in Obj-C. Nil is nothing
Since %li is expecting a long integer, and nil is not literal convertible, and Swift is statically typed, you have to unwrap the number and make sure it is not nil (Zero is not nil).
This might not be the 100% exact technical explanation. But it should give the rough idea.
You are making it more difficult than it has to be. Values in dictionaries are optional because you might not get a value for a particular key. To be safe, you bind the value from the dictionary in an if let to make sure you actually have an object, then use string interpolation to set the cell's text property.
// This is all so you can test it in a playground
var dictionary = [String : AnyObject]()
let kSomeKey = "price"
dictionary[kSomeKey] = NSNumber(long: 12)
// Bind the value out of the dictionary
if let priceNumber = dictionary[kSomeKey] as? NSNumber {
// priceNumber is guaranteed to be an instance of NSNumber at this point
cell.titleLabel.text = "The price is £\(priceNumber)")
}

"if let" statement executed despite value being nil

I have an "if let" statement that is being executed, despite the "let" part being nil.
if let leftInc : Double? = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!]! {
println(leftInc)
let valueString : String = formatter.stringFromNumber(NSNumber(double: leftInc!))!
self.leftIncisorTextField?.text = valueString
self.btnLeftIncisor.associatedLabel?.text = valueString
}
// self.analysis.inputs is a Dictionary<String, Double?>
The inputs dictionary holds information entered by the user - either a number, or nil if they haven't entered anything in the matching field yet.
Under the previous version of Swift, the code was written as this:
if let leftInc : Double? = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!]?? {
and worked correctly.
I saw a similar question here, but in that instance the problem seemed to be the result of using Any?, which is not the case here.
Swift 2.2
In your if let you define another optional, that's why nil is a legitimate case. if let is intended mainly to extract (maybe) non optional value from an optional.
You might try:
if let leftInc : Double = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!].flatMap ({$0}) {
// leftInc is not an optional in this scope
...
}
Anyway I'd consider to not do it as a one liner but take advantage of guard case. Just in order to enhance readability. And avoid bang operator (!).
The if-let is for unwrapping optionals. You are allowing nil values by setting the type to an optional Double.
The if statement should be:
if let leftInc = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!] as? Double{
...
}
This will attempt to get an object out of inputs, if that fails it returns nil and skips it. If it does return something it will attempt to convert it to a Double. If that fails it skips the if statement as well.
if inputs is a dictionary like [Something:Double] then you don't need the last as? Double as indexing the dictionary will return a Double?
I recommend reading the swift book on optional chaining.
You could break it down further -
if let optionalDouble = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!], leftInc = optionalDouble {
....
}
as your dictionary has optional values - this way of writing it might make it clearer what's going on
if let k = dict["someKey"]{}, dict["someKey"] will be an object of type Any
this can bypass a nill
So do a typecast to get it correct like if let k = dict["someKey"] as! String {}

How to check if a variable is nil

I have a variable
var a: [AnyObject? -> Void]
and I am adding data in to it by append method. Now I want to check if the variable is nil or not. I tried using [] but not working and also tried "", this also not working, can anyone tell what is the meaning of this variable and how to check if it is nil.
As far as I understand, var a is an Array of functions that take an optional Object of any type, and return void. So these functions's parameter IS optional, but the Array itself isn't : it cannot be nil, or it would be declared [AnyObject? -> Void]? , no?
EDIT : if, nevertheless, you declared this a as an optional (but WHY would you do that ?) - adding a ? - you check an optional existence with if let :
if let b = a {
// a not nil, do some stuff
} else {
// a is null
}
If you just want to check if the array is empty, use isEmpty method from Swift Array
Update: Xcode 7.3 Swift 2.2
If you want to check if a variable is nil you should use if let to unwrap if for you. There is no need to create a second var.
let str = "123"
var a = Int(str)
if let a = a {
print(a)
}
Or
if let a = Int(str) {
print(a)
}
In Swift, nil is not a pointer—it is the absence of a value of a certain type. Optionals of any type can be set to nil, not just object types.
So, You can check it with below code:
let possibleNumber = "123"
let convertedNumber = possibleNumber.toInt()
if convertedNumber != nil {
println("convertedNumber contains some integer value.")
}
// prints "convertedNumber contains some integer value."
Please refer this about nil for more information.
In Swift 3.0
if let imageURL = dictObj["list_image"] as? String {
print(imageURL)
}
You can use if let. if let is a special structure in Swift that allows you to check if an Optional holds a value, and in case it does – do something with the unwrapped value.
var a:Int=0
if let b=a{
println(a)
} else {
println("Value - nil")
}
But for Strings you can also use .isEmpty() If you have initialized it to "".
var str:String=""
if !str.isEmpty(){
println(str)
}
For me none of the above solutions worked when I was using an AVFoundation object.
I would get Type 'AVCaptureDeviceInput does not conform to protocol 'BooleanType' when I tried if (audioDeviceInput) and I would get Binary operator '!=' cannot be applied to operands of type 'AVCaptureDeviceInput' and 'nil'.
Solution in my situation
if (audioDeviceInput.isEqual(nil))
nil is a pointer like any other and can be referenced as such, which is why this works.

Printing optional variable

I am trying with these lines of code
class Student {
var name: String
var age: Int?
init(name: String) {
self.name = name
}
func description() -> String {
return age != nil ? "\(name) is \(age) years old." : "\(name) hides his age."
}
}
var me = Student(name: "Daniel")
println(me.description())
me.age = 18
println(me.description())
Above code produces as follow
Daniel hides his age.
Daniel is Optional(18) years old.
My question is why there is Optional (18) there, how can I remove the optional and just printing
Daniel is 18 years old.
You have to understand what an Optional really is. Many Swift beginners think var age: Int? means that age is an Int which may or may not have a value. But it means that age is an Optional which may or may not hold an Int.
Inside your description() function you don't print the Int, but instead you print the Optional. If you want to print the Int you have to unwrap the Optional. You can use "optional binding" to unwrap an Optional:
if let a = age {
// a is an Int
}
If you are sure that the Optional holds an object, you can use "forced unwrapping":
let a = age!
Or in your example, since you already have a test for nil in the description function, you can just change it to:
func description() -> String {
return age != nil ? "\(name) is \(age!) years old." : "\(name) hides his age."
}
To remove it, there are three methods you could employ.
If you are absolutely sure of the type, you can use an exclamation mark to force unwrap it, like this:
// Here is an optional variable:
var age: Int?
// Here is how you would force unwrap it:
var unwrappedAge = age!
If you do force unwrap an optional and it is equal to nil, you may encounter this crash error:
This is not necessarily safe, so here's a method that might prevent crashing in case you are not certain of the type and value:
Methods 2 and three safeguard against this problem.
The Implicitly Unwrapped Optional
if let unwrappedAge = age {
// continue in here
}
Note that the unwrapped type is now Int, rather than Int?.
The guard statement
guard let unwrappedAge = age else {
// continue in here
}
From here, you can go ahead and use the unwrapped variable. Make sure only to force unwrap (with an !), if you are sure of the type of the variable.
Good luck with your project!
For testing/debugging purposes I often want to output optionals as strings without always having to test for nil values, so I created a custom operator.
I improved things even further after reading this answer in another question.
fileprivate protocol _Optional {
func unwrappedString() -> String
}
extension Optional: _Optional {
fileprivate func unwrappedString() -> String {
switch self {
case .some(let wrapped as _Optional): return wrapped.unwrappedString()
case .some(let wrapped): return String(describing: wrapped)
case .none: return String(describing: self)
}
}
}
postfix operator ~? { }
public postfix func ~? <X> (x: X?) -> String {
return x.unwrappedString
}
Obviously the operator (and its attributes) can be tweaked to your liking, or you could make it a function instead. Anyway, this enables you to write simple code like this:
var d: Double? = 12.34
print(d) // Optional(12.34)
print(d~?) // 12.34
d = nil
print(d~?) // nil
Integrating the other guy's protocol idea made it so this even works with nested optionals, which often occur when using optional chaining. For example:
let i: Int??? = 5
print(i) // Optional(Optional(Optional(5)))
print("i: \(i~?)") // i: 5
Update
Simply use me.age ?? "Unknown age!". It works in 3.0.2.
Old Answer
Without force unwrapping (no mach signal/crash if nil) another nice way of doing this would be:
(result["ip"] ?? "unavailable").description.
result["ip"] ?? "unavailable" should have work too, but it doesn't, not in 2.2 at least
Of course, replace "unavailable" with whatever suits you: "nil", "not found" etc
To unwrap optional use age! instead of age. Currently your are printing optional value that could be nil. Thats why it wrapped with Optional.
In swift Optional is something which can be nil in some cases. If you are 100% sure that a variable will have some value always and will not return nil the add ! with the variable to force unwrap it.
In other case if you are not much sure of value then add an if let block or guard to make sure that value exists otherwise it can result in a crash.
For if let block :
if let abc = any_variable {
// do anything you want with 'abc' variable no need to force unwrap now.
}
For guard statement :
guard is a conditional structure to return control if condition is not met.
I prefer to use guard over if let block in many situations as it allows us to return the function if a particular value does not exist.
Like when there is a function where a variable is integral to exist, we can check for it in guard statement and return of it does not exist.
i-e;
guard let abc = any_variable else { return }
We if variable exists the we can use 'abc' in the function outside guard scope.
age is optional type: Optional<Int> so if you compare it to nil it returns false every time if it has a value or if it hasn't. You need to unwrap the optional to get the value.
In your example you don't know is it contains any value so you can use this instead:
if let myAge = age {
// there is a value and it's currently undraped and is stored in a constant
}
else {
// no value
}
I did this to print the value of string (property) from another view controller.
ViewController.swift
var testString:NSString = "I am iOS Developer"
SecondViewController.swift
var obj:ViewController? = ViewController(nibName: "ViewController", bundle: nil)
print("The Value of String is \(obj!.testString)")
Result :
The Value of String is I am iOS Developer
Check out the guard statement:
for student in class {
guard let age = student.age else {
continue
}
// do something with age
}
When having a default value:
print("\(name) is \(age ?? 0) years old")
or when the name is optional:
print("\(name ?? "unknown") is \(age) years old")
I was getting the Optional("String") in my tableview cells.
The first answer is great. And helped me figure it out. Here is what I did, to help the rookies out there like me.
Since I am creating an array in my custom object, I know that it will always have items in the first position, so I can force unwrap it into another variable. Then use that variable to print, or in my case, set to the tableview cell text.
let description = workout.listOfStrings.first!
cell.textLabel?.text = description
Seems so simple now, but took me a while to figure out.
This is not the exact answer to this question, but one reason for this kind of issue.
In my case,
I was not able to remove Optional from a String with "if let" and "guard let".
So use AnyObject instead of Any to remove optional from a string in swift.
Please refer link for the answer.
https://stackoverflow.com/a/51356716/8334818
If you just want to get rid of strings like Optional(xxx) and instead get xxx or nil when you print some values somewhere (like logs), you can add the following extension to your code:
extension Optional {
var orNil: String {
if self == nil {
return "nil"
}
return "\(self!)"
}
}
Then the following code:
var x: Int?
print("x is \(x.orNil)")
x = 10
print("x is \(x.orNil)")
will give you:
x is nil
x is 10
PS. Property naming (orNil) is obviously not the best, but I can't come up with something more clear.
With the following code you can print it or print some default value. That's what XCode generally recommend I think
var someString: String?
print("Some string is \(someString ?? String("Some default"))")
If you are printing some optional which is not directly printable but has a 'to-printable' type method, such as UUID, you can do something like this:
print("value is: \(myOptionalUUID?.uuidString ?? "nil")")
eg
let uuid1 : UUID? = nil
let uuid2 : UUID? = UUID.init()
print("uuid1: \(uuid1?.uuidString ?? "nil")")
print("uuid2: \(uuid2?.uuidString ?? "nil")")
-->
uuid1: nil
uuid2: 0576137D-C6E6-4804-848E-7B4011B40C11

What is an optional value in Swift?

From Apple's documentation:
You can use if and let together to work with values that might be missing. These values are represented as optionals. An optional value either contains a value or contains nil to indicate that the value is missing. Write a question mark (?) after the type of a value to mark the value as optional.
Why would you want to use an optional value?
An optional in Swift is a type that can hold either a value or no value. Optionals are written by appending a ? to any type:
var name: String? = "Bertie"
Optionals (along with Generics) are one of the most difficult Swift concepts to understand. Because of how they are written and used, it's easy to get a wrong idea of what they are. Compare the optional above to creating a normal String:
var name: String = "Bertie" // No "?" after String
From the syntax it looks like an optional String is very similar to an ordinary String. It's not. An optional String is not a String with some "optional" setting turned on. It's not a special variety of String. A String and an optional String are completely different types.
Here's the most important thing to know: An optional is a kind of container. An optional String is a container which might contain a String. An optional Int is a container which might contain an Int. Think of an optional as a kind of parcel. Before you open it (or "unwrap" in the language of optionals) you won't know if it contains something or nothing.
You can see how optionals are implemented in the Swift Standard Library by typing "Optional" into any Swift file and ⌘-clicking on it. Here's the important part of the definition:
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
Optional is just an enum which can be one of two cases: .none or .some. If it's .some, there's an associated value which, in the example above, would be the String "Hello". An optional uses Generics to give a type to the associated value. The type of an optional String isn't String, it's Optional, or more precisely Optional<String>.
Everything Swift does with optionals is magic to make reading and writing code more fluent. Unfortunately this obscures the way it actually works. I'll go through some of the tricks later.
Note: I'll be talking about optional variables a lot, but it's fine to create optional constants too. I mark all variables with their type to make it easier to understand type types being created, but you don't have to in your own code.
How to create optionals
To create an optional, append a ? after the type you wish to wrap. Any type can be optional, even your own custom types. You can't have a space between the type and the ?.
var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)
// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}
Using optionals
You can compare an optional to nil to see if it has a value:
var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
print("There is a name")
}
if name == nil { // Could also use an "else"
print("Name has no value")
}
This is a little confusing. It implies that an optional is either one thing or another. It's either nil or it's "Bob". This is not true, the optional doesn't transform into something else. Comparing it to nil is a trick to make easier-to-read code. If an optional equals nil, this just means that the enum is currently set to .none.
Only optionals can be nil
If you try to set a non-optional variable to nil, you'll get an error.
var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'
Another way of looking at optionals is as a complement to normal Swift variables. They are a counterpart to a variable which is guaranteed to have a value. Swift is a careful language that hates ambiguity. Most variables are define as non-optionals, but sometimes this isn't possible. For example, imagine a view controller which loads an image either from a cache or from the network. It may or may not have that image at the time the view controller is created. There's no way to guarantee the value for the image variable. In this case you would have to make it optional. It starts as nil and when the image is retrieved, the optional gets a value.
Using an optional reveals the programmers intent. Compared to Objective-C, where any object could be nil, Swift needs you to be clear about when a value can be missing and when it's guaranteed to exist.
To use an optional, you "unwrap" it
An optional String cannot be used in place of an actual String. To use the wrapped value inside an optional, you have to unwrap it. The simplest way to unwrap an optional is to add a ! after the optional name. This is called "force unwrapping". It returns the value inside the optional (as the original type) but if the optional is nil, it causes a runtime crash. Before unwrapping you should be sure there's a value.
var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")
name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.
Checking and using an optional
Because you should always check for nil before unwrapping and using an optional, this is a common pattern:
var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
let unwrappedMealPreference: String = mealPreference!
print("Meal: \(unwrappedMealPreference)") // or do something useful
}
In this pattern you check that a value is present, then when you are sure it is, you force unwrap it into a temporary constant to use. Because this is such a common thing to do, Swift offers a shortcut using "if let". This is called "optional binding".
var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
print("Meal: \(unwrappedMealPreference)")
}
This creates a temporary constant (or variable if you replace let with var) whose scope is only within the if's braces. Because having to use a name like "unwrappedMealPreference" or "realMealPreference" is a burden, Swift allows you to reuse the original variable name, creating a temporary one within the bracket scope
var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
print("Meal: \(mealPreference)") // separate from the other mealPreference
}
Here's some code to demonstrate that a different variable is used:
var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"
Optional binding works by checking to see if the optional equals nil. If it doesn't, it unwraps the optional into the provided constant and executes the block. In Xcode 8.3 and later (Swift 3.1), trying to print an optional like this will cause a useless warning. Use the optional's debugDescription to silence it:
print("\(mealPreference.debugDescription)")
What are optionals for?
Optionals have two use cases:
Things that can fail (I was expecting something but I got nothing)
Things that are nothing now but might be something later (and vice-versa)
Some concrete examples:
A property which can be there or not there, like middleName or spouse in a Person class
A method which can return a value or nothing, like searching for a match in an array
A method which can return either a result or get an error and return nothing, like trying to read a file's contents (which normally returns the file's data) but the file doesn't exist
Delegate properties, which don't always have to be set and are generally set after initialization
For weak properties in classes. The thing they point to can be set to nil at any time
A large resource that might have to be released to reclaim memory
When you need a way to know when a value has been set (data not yet loaded > the data) instead of using a separate dataLoaded Boolean
Optionals don't exist in Objective-C but there is an equivalent concept, returning nil. Methods that can return an object can return nil instead. This is taken to mean "the absence of a valid object" and is often used to say that something went wrong. It only works with Objective-C objects, not with primitives or basic C-types (enums, structs). Objective-C often had specialized types to represent the absence of these values (NSNotFound which is really NSIntegerMax, kCLLocationCoordinate2DInvalid to represent an invalid coordinate, -1 or some negative value are also used). The coder has to know about these special values so they must be documented and learned for each case. If a method can't take nil as a parameter, this has to be documented. In Objective-C, nil was a pointer just as all objects were defined as pointers, but nil pointed to a specific (zero) address. In Swift, nil is a literal which means the absence of a certain type.
Comparing to nil
You used to be able to use any optional as a Boolean:
let leatherTrim: CarExtras? = nil
if leatherTrim {
price = price + 1000
}
In more recent versions of Swift you have to use leatherTrim != nil. Why is this? The problem is that a Boolean can be wrapped in an optional. If you have Boolean like this:
var ambiguous: Boolean? = false
it has two kinds of "false", one where there is no value and one where it has a value but the value is false. Swift hates ambiguity so now you must always check an optional against nil.
You might wonder what the point of an optional Boolean is? As with other optionals the .none state could indicate that the value is as-yet unknown. There might be something on the other end of a network call which takes some time to poll. Optional Booleans are also called "Three-Value Booleans"
Swift tricks
Swift uses some tricks to allow optionals to work. Consider these three lines of ordinary looking optional code;
var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }
None of these lines should compile.
The first line sets an optional String using a String literal, two different types. Even if this was a String the types are different
The second line sets an optional String to nil, two different types
The third line compares an optional string to nil, two different types
I'll go through some of the implementation details of optionals that allow these lines to work.
Creating an optional
Using ? to create an optional is syntactic sugar, enabled by the Swift compiler. If you want to do it the long way, you can create an optional like this:
var name: Optional<String> = Optional("Bob")
This calls Optional's first initializer, public init(_ some: Wrapped), which infers the optional's associated type from the type used within the parentheses.
The even longer way of creating and setting an optional:
var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")
Setting an optional to nil
You can create an optional with no initial value, or create one with the initial value of nil (both have the same outcome).
var name: String?
var name: String? = nil
Allowing optionals to equal nil is enabled by the protocol ExpressibleByNilLiteral (previously named NilLiteralConvertible). The optional is created with Optional's second initializer, public init(nilLiteral: ()). The docs say that you shouldn't use ExpressibleByNilLiteral for anything except optionals, since that would change the meaning of nil in your code, but it's possible to do it:
class Clint: ExpressibleByNilLiteral {
var name: String?
required init(nilLiteral: ()) {
name = "The Man with No Name"
}
}
let clint: Clint = nil // Would normally give an error
print("\(clint.name)")
The same protocol allows you to set an already-created optional to nil. Although it's not recommended, you can use the nil literal initializer directly:
var name: Optional<String> = Optional(nilLiteral: ())
Comparing an optional to nil
Optionals define two special "==" and "!=" operators, which you can see in the Optional definition. The first == allows you to check if any optional is equal to nil. Two different optionals which are set to .none will always be equal if the associated types are the same. When you compare to nil, behind the scenes Swift creates an optional of the same associated type, set to .none then uses that for the comparison.
// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
print("tuxedoRequired is nil")
}
The second == operator allows you to compare two optionals. Both have to be the same type and that type needs to conform to Equatable (the protocol which allows comparing things with the regular "==" operator). Swift (presumably) unwraps the two values and compares them directly. It also handles the case where one or both of the optionals are .none. Note the distinction between comparing to the nil literal.
Furthermore, it allows you to compare any Equatable type to an optional wrapping that type:
let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
print("It's a match!") // Prints "It's a match!"
}
Behind the scenes, Swift wraps the non-optional as an optional before the comparison. It works with literals too (if 23 == numberFromString {)
I said there are two == operators, but there's actually a third which allow you to put nil on the left-hand side of the comparison
if nil == name { ... }
Naming Optionals
There is no Swift convention for naming optional types differently from non-optional types. People avoid adding something to the name to show that it's an optional (like "optionalMiddleName", or "possibleNumberAsString") and let the declaration show that it's an optional type. This gets difficult when you want to name something to hold the value from an optional. The name "middleName" implies that it's a String type, so when you extract the String value from it, you can often end up with names like "actualMiddleName" or "unwrappedMiddleName" or "realMiddleName". Use optional binding and reuse the variable name to get around this.
The official definition
From "The Basics" in the Swift Programming Language:
Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes. Optionals are safer and more expressive than nil pointers in Objective-C and are at the heart of many of Swift’s most powerful features.
Optionals are an example of the fact that Swift is a type safe language. Swift helps you to be clear about the types of values your code can work with. If part of your code expects a String, type safety prevents you from passing it an Int by mistake. This enables you to catch and fix errors as early as possible in the development process.
To finish, here's a poem from 1899 about optionals:
Yesterday upon the stair
I met a man who wasn’t there
He wasn’t there again today
I wish, I wish he’d go away
Antigonish
More resources:
The Swift Programming Guide
Optionals in Swift (Medium)
WWDC Session 402 "Introduction to Swift" (starts around 14:15)
More optional tips and tricks
Let's take the example of an NSError, if there isn't an error being returned you'd want to make it optional to return Nil. There's no point in assigning a value to it if there isn't an error..
var error: NSError? = nil
This also allows you to have a default value. So you can set a method a default value if the function isn't passed anything
func doesntEnterNumber(x: Int? = 5) -> Bool {
if (x == 5){
return true
} else {
return false
}
}
You can't have a variable that points to nil in Swift — there are no pointers, and no null pointers. But in an API, you often want to be able to indicate either a specific kind of value, or a lack of value — e.g. does my window have a delegate, and if so, who is it? Optionals are Swift's type-safe, memory-safe way to do this.
I made a short answer, that sums up most of the above, to clean the uncertainty that was in my head as a beginner:
Opposed to Objective-C, no variable can contain nil in Swift, so the Optional variable type was added (variables suffixed by "?"):
var aString = nil //error
The big difference is that the Optional variables don't directly store values (as a normal Obj-C variables would) they contain two states: "has a value" or "has nil":
var aString: String? = "Hello, World!"
aString = nil //correct, now it contains the state "has nil"
That being, you can check those variables in different situations:
if let myString = aString? {
println(myString)
}
else {
println("It's nil") // this will print in our case
}
By using the "!" suffix, you can also access the values wrapped in them, only if those exist. (i.e it is not nil):
let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!
println(anotherString) //it will print "Hello, World!"
That's why you need to use "?" and "!" and not use all of them by default. (this was my biggest bewilderment)
I also agree with the answer above: Optional type cannot be used as a boolean.
In objective C variables with no value were equal to 'nil'(it was also possible to use 'nil' values same as 0 and false), hence it was possible to use variables in conditional statements (Variables having values are same as 'TRUE' and those with no values were equal to 'FALSE').
Swift provides type safety by providing 'optional value'. i.e. It prevents errors formed from assigning variables of different types.
So in Swift, only booleans can be provided on conditional statements.
var hw = "Hello World"
Here, even-though 'hw' is a string, it can't be used in an if statement like in objective C.
//This is an error
if hw
{..}
For that it needs to be created as,
var nhw : String? = "Hello World"
//This is correct
if nhw
{..}
Optional value allows you to show absence of value. Little bit like NULL in SQL or NSNull in Objective-C. I guess this will be an improvement as you can use this even for "primitive" types.
// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
case None
case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/gb/jEUH0.l
An optional means that Swift is not entirely sure if the value corresponds to the type: for example, Int? means that Swift is not entirely sure whether the number is an Int.
To remove it, there are three methods you could employ.
1) If you are absolutely sure of the type, you can use an exclamation mark to force unwrap it, like this:
// Here is an optional variable:
var age: Int?
// Here is how you would force unwrap it:
var unwrappedAge = age!
If you do force unwrap an optional and it is equal to nil, you may encounter this crash error:
This is not necessarily safe, so here's a method that might prevent crashing in case you are not certain of the type and value:
Methods 2 and three safeguard against this problem.
2) The Implicitly Unwrapped Optional
if let unwrappedAge = age {
// continue in here
}
Note that the unwrapped type is now Int, rather than Int?.
3) The guard statement
guard let unwrappedAge = age else {
// continue in here
}
From here, you can go ahead and use the unwrapped variable. Make sure only to force unwrap (with an !), if you are sure of the type of the variable.
Good luck with your project!
When i started to learn Swift it was very difficult to realize why optional.
Lets think in this way.
Let consider a class Person which has two property name and company.
class Person: NSObject {
var name : String //Person must have a value so its no marked as optional
var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible
init(name:String,company:String?) {
self.name = name
self.companyName = company
}
}
Now lets create few objects of Person
var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil
But we can not pass Nil to name
var personWithNoName:Person = Person.init(name: nil, company: nil)
Now Lets talk about why we use optional?.
Lets consider a situation where we want to add Inc after company name like apple will be apple Inc. We need to append Inc after company name and print.
print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.
Now lets study why optional takes into place.
if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.
print(companyString+" Inc") //Will never executed and no crash!!!
}
Lets replace bob with tom
if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.
print(companyString+" Inc") //Will executed and no crash!!!
}
And Congratulation! we have properly deal with optional?
So the realization points are
We will mark a variable as optional if its possible to be nil
If we want to use this variable somewhere in code compiler will
remind you that we need to check if we have proper deal with that variable
if it contain nil.
Thank you...Happy Coding
Lets Experiment with below code Playground.I Hope will clear idea what is optional and reason of using it.
var sampleString: String? ///Optional, Possible to be nil
sampleString = nil ////perfactly valid as its optional
sampleString = "some value" //Will hold the value
if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.
print(value+value) ////Sample String merged into Two
}
sampleString = nil // value is nil and the
if let value = sampleString{
print(value + value) ///Will Not execute and safe for nil checking
}
// print(sampleString! + sampleString!) //this line Will crash as + operator can not add nil
From https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html:
Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil. If the optional contains a value, the property, method, or subscript call succeeds; if the optional is nil, the property, method, or subscript call returns nil. Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.
To understand deeper, read the link above.
Well...
? (Optional) indicates your variable may contain a nil value while ! (unwrapper) indicates your variable must have a memory (or value) when it is used (tried to get a value from it) at runtime.
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.
To reflect the fact that optional chaining can be called on a nil value, the result of an optional chaining call is always an optional value, even if the property, method, or subscript you are querying returns a nonoptional value. You can use this optional return value to check whether the optional chaining call was successful (the returned optional contains a value), or did not succeed due to a nil value in the chain (the returned optional value is nil).
Specifically, the result of an optional chaining call is of the same type as the expected return value, but wrapped in an optional. A property that normally returns an Int will return an Int? when accessed through optional chaining.
var defaultNil : Int? // declared variable with default nil value
println(defaultNil) >> nil
var canBeNil : Int? = 4
println(canBeNil) >> optional(4)
canBeNil = nil
println(canBeNil) >> nil
println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper
var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4
var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error
Here is basic tutorial in detail, by Apple Developer Committee: Optional Chaining
An optional in Swift is a type that can hold either a value or no value. Optionals are written by appending a ? to any type:
var name: String?
You can refer to this link to get knowledge in deep: https://medium.com/#agoiabeladeyemi/optionals-in-swift-2b141f12f870
There are lots of errors which are caused by people trying to use a value which is not set, sometime this can cause a crash, in objective c trying to call the methods of a nil object reference would just be ignored, so some piece of your code not executing and the compiler or written code has no way of telling your why. An optional argument let you have variables that can never be nil, and if you try to do build it the compiler can tell you before your code has even had a chance to run, or you can decide that its appropriate for the object to be undefined, and then the compiler can tell you when you try to write something that doesn't take this into account.
In the case of calling a possible nil object you can just go
object?.doSomthing()
You have made it explicit to the compiler and any body who reads your code, that its possible object is nil and nothing will happen. Some times you have a few lines of code you only want to occur if the value exists, so you can do
if let obj = object {
obj.doSomthing()
doSomethingto(obj)
}
The two statements will only execute if object is something, simarly you may want to stop the rest of the entire block of code if its not something
guard let obj = object {
return
}
obj.doSomthing()
doSomethingto(obj)
This can be simpler to read if everything after is only applicable if object is something, another possiblity is you want to use a default value
let obj = object ?? <default-object>
obj.doSomthing()
doSomethingto(obj)
Now obj will be assigned to something even if its a default value for the type
options are useful in situation where a value may not gain a value until some event has occurred or you can use setting an option to nil as a way to say its no longer relevant or needs to be set again and everything that uses it has no point it doing anything with it until it is set, one way I like to use optionals is to tell me something has to be done or if has already been done for example
func eventFired() {
guard timer == nil else { return }
timer = scheduleTimerToCall(method, in: 60)
}
func method() {
doSomthing()
timer = nil
}
This sudo code can call eventFired many times, but it's only on the first call that a timer is scheduled, once the schedule executes, it runs some method and sets timer back to nil so another timer can be scheduled.
Once you get around your head around variables being in an undefined state you can use that for all sort of thing.
It's very simple. Optional (in Swift) means a variable/constant can be nullable. You can see that Kotlin language implements the same thing but never calls it an 'optional'. For example:
var lol: Laugh? = nil
is equivalent to this in Kotlin:
var lol: Laugh? = null
or this in Java:
#Nullable Laugh lol = null;
In the very first example, if you don't use the ?symbol in front of the object type, then you will have an error. Because the question mark means that the variable/constant can be null, therefore being called optional.
Here is an equivalent optional declaration in Swift:
var middleName: String?
This declaration creates a variable named middleName of type String. The question mark (?) after the String variable type indicates that the middleName variable can contain a value that can either be a String or nil. Anyone looking at this code immediately knows that middleName can be nil. It's self-documenting!
If you don't specify an initial value for an optional constant or variable (as shown above) the value is automatically set to nil for you. If you prefer, you can explicitly set the initial value to nil:
var middleName: String? = nil
for more detail for optional read below link
http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values