Mastering Advanced Swift: Optionals, Collections, Closures, Protocols, and Error Handling
Advanced Swift Concepts — Part 3 of series
Before starting, Open Xcode, Click on File => New => Playground => iOS => Blank, and create a new playground to run Swift Code.
Optionals
Swift’s powerful Optionals feature lets you save a value that that could be nil
(no value).
var optionalString: String? = "Hello"
print(optionalString) // Output: Optional("Hello")
Using if-let or guard-let statements, or by setting a default value, you can safely unwrap an optional:
// if-let
if let unwrappedString = optionalString {
print(unwrappedString) // Safe unwrapping
} else {
print("The optional was nil.")
}
// guard-let
func someFunction() {
guard let unwrappedString = optionalString else {
print("The optional was nil.")
return
}
print(unwrappedString) // Safe to use 'unwrappedString' after this point
}
// default
print(optionalString ?? "DefaultValue")
Collections
Swift provides arrays, sets, and dictionaries for storing collections of values.
Array: Ordered collections of values.
var someInts = [Int]() // An empty array
var moreInts: [Int] = [10, 20, 30]
Set: Collections of unique values.
var aSet: Set<Int> = [1, 2, 3, 4, 5]
Dictionary: Unordered collections of key-value associations.
var namesOfIntegers: [Int: String] = [1: "one", 2: "two", 3: "three"]
Closures
Self-contained functional blocks called closures can be utilised and passed around within your code.
let greetingClosure = { (name: String) in
print("Hello, \(name)")
}
greetingClosure("World")
Constants and variables from the surrounding context can be captured by closures.
Protocols
A protocol is a set of guidelines that specify the attributes, methods, and other needs necessary for a certain piece of functionality like a blueprint.
protocol FullyNamed {
var fullName: String { get }
}
struct Person: FullyNamed {
var fullName: String
}
let john = Person(fullName: "John Appleseed")
Extensions
Extensions provide an existing class, structure, enum, or protocol type new functionalities.
extension Int {
func squared() -> Int {
return self * self
}
}
print(3.squared()) // Output: 9
Enums
Enums allow you to work with a set of related values in your code in a type-safe manner by defining a common type for them.
enum Direction {
case north
case south
case east
case west
}
var directionToHead = Direction.west
With features like related values, Swift enums are far more powerful than enums in many other languages.
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
Error Handling
For the purpose of propagating, catching, modifying, and throwing recoverable errors at runtime, Swift offers first-class support.
enum PrinterError: Error {
case outOfPaper
case noToner
case onFire
}
func send(job: Int, toPrinter printerName: String) throws -> String {
if printerName == "Never Has Toner" {
throw PrinterError.noToner
}
return "Job sent"
}
Exercise: Practice With Advanced Swift
Firstly, a Swift closure that takes a string and prints it. Next, create an enum with a few possible UI states (such as loading, error, and success), and then write a function that accepts the enum as an input and outputs a message according to each state.
These language features are essential to learning Swift and becoming a proficient iOS developer because they are often utilised in UI programming, particularly when handling user interactions and asynchronous processes.
After you understand these ideas, we’ll go on to leverage UI with iOS-specific APIs, and eventually creating an entire application. Practice these ideas because they will serve as the foundation for your understanding of iOS development.
Practice. Experiment. Learn