This topic is very confusing for the learner. I think you're confused about its format and why Swift has it. Swift Optional is a very important underlying concept in Swift programming. Optional is something that you are doing a lot of work with in developing Swift Code.
An optional is a
Optional allow you to write flexible and more safe code,Question mark (?) means it can be nil or some value.
Optionals introduce a high level of type-safety in Swift code. Additionally, nil
Swift Programming 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”. Using optionals is similar to using nil
with pointers in Objective-C, but they work for any type, not just classes. Not only are optionals safer and more expressive than nil
pointers in Objective-C, they’re at the heart of many of Swift’s most powerful features. e.g
struct Person {
var title: String?
var name: String!
}
You see here Swift introduces the optional concept
And Swift uses question mark and
- 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.
- When a method that's supposed to return a value fails. An optional is returned to enforce checking against nil.
- When you want to use a method, but don't want to provide certain arguments. If those are optional, you can just pass nil.
A- Forced unwrapping
var myString:String?
myString = "Hii, AppCodeZip!"
let obj = myString! // forced unwrapping Success!!!
print(obj) // Hii, AppCodeZip!
let nickName:String?
let name = nickName! //The value is not set.
print(name) // forced unwrapping Error. (Constant 'nickName' used before being initialized)
B- Implicit unwrapping
// Implicitly unwrapped optional
var example:String! = nil
test(example) // Runtime error, not compiler error
example = "Hello"
// no exclamation needed, it's implicit
test(example) // "Hello"
if tweet !=nil {
println(“tweet is not nil)
} else {
println(“tweet is nil”)
}
if let actualTweet = tweet {
println(“The value is: \(actualTweet)”)
} else {
println(“Gracefully go to this line when tweet is nil”)
}
let name: String? = "AppCodeZip"
if let unwrappedName = name {
print("Hello, \(unwrappedName)!")
} else {
print("Hello, anonymous!")
}
Using nil coalescing we could collapse that down to just two lines:
let unwrappedName = name ?? "anonymous"
print("Hello, \(unwrappedName)")
E. Optional Chaining
Optional chaining looks simple but is deceptively powerful. You simply use a ? when referencing optional values.
Let’s look at a simple example with a person and optional address (which also has an optional postcode).
class Person {
var name: String
var address: Address?
init(name: String) { self.name = name }
}
class Address {
var streetReference: String
var postCode: String?
init(streetReference: String) {
self.streetReference = streetReference
}
}
let andy = Person(name: "Andy")
let streetRef = andy.address?.streetReference // chaining
let streetRef2 = andy.address!.streetReference // forced unwrapping
address is an optional Address, Address?, and hasn't been supplied here so the assignment of streetRef will fail (but not the program) at the address segment.
With optional chaining, by using ?, streetRef will be defined as an optional String, String?, because Address.streetReference is a String.
When any type is referenced by optional chaining the value returned is an Optional version of that type.
streetRef2 however, will be a String, because Address.streetReference is a String and is being accessed directly by forced unwrapping.
In this example, because address is not set, both assignments will fail, however, streetRef will be assigned nil and the program will continue, whereas the program will crash once it tries to assign streetRef2 because forced unwrapping will encounter the nil in address.
With optional chaining, multiple values can be optionals.
let postCode = andy.address?.postCode?
Again, postCode will be an optional String, String?. Note, that Address.postCode is already defined as String?. In this case the assigned type does not become an optional optional, one level of optionality is sufficient, so it remains String?.
Typically, you might combine optional chaining with ‘if let’:
if let postCode = andy.address?.postCode? {
sendNewsletter(postCode)
}
Optional chaining can also be used on the assigned value, for example:
andy.address?.postCode = "ABC 123"
In this scenario, if address is set, then the postCode will be set to “ABC 123”. If address is not set, then the assignment won't happen.
However, note again that this is a silent failure, you don't get any feedback on whether the assignment happened.
So this might be a scenario to make use of nil comparison:
if (andy.address?.postCode = "ABC 123") != nil {
print("Post Code was changed")
} else {
print("Post Code was NOT changed")
}
The reason this works is because assignments have an implicit return type of Void and when optional chaining is used that return type becomes an optional Void, Void? and so it can be tested for nil.
F. Guard let.
It’s probably also worth mentioning the guard statement. The guard statement is a safety feature that can be used independently of optionals and probably deserves a whole topic to itself, but one thing it supports is an alternative form of optional binding and so it’s worth taking a quick look at that:
func updatePostCode(address: Address?, postCode: String?) {
guard let validAddress = address else { return }
guard let validPostCode = postCode else { return }
validAddress.postCode = validPostCode
}
The unusual behaviour of guard of is that while it looks like an if let statement, the bound variables scope rules are different and it also requires an else block which must explicitly state where to transfer control if the assignment or test fails.
The bound optionals specified in the guard statement (validAddress and validPostCode in this example) are available in the same scope where the guard statement is written, which in this example means the scope of the function updatePostCode(: Address?, :String?). This means the valid bound versions of the variables are then available for use in the function. This seems a bit weird at first, but it’s a very useful feature.
HAPPY LEARNING!
Memory Management with ARC and Avoiding retain cycles with Weak and Unowned in Swift.
How to create Certificate Signing Request (CSR) in macOS (iOS) Keychain Access
Swift 5.2 Generics Explained - How to Use Generics in iOS Apps
How to generate .ipa file for In-House and distribute enterprise iOS app inside a company
How to Create an App ID and Bundle Identifier for your iOS App in Xcode 11 (2020)
Creating the iOS Development & Distribution Certificate and .p12 File
Development Xcode11 Import Development and Distribution Provisioning Profile
0 Comments