🚀 Swift Introduction
🎯 Complete Definition
Swift is a modern, safe, fast, and expressive multi-paradigm compiled programming language developed by Apple Inc. and the open-source community. First announced at WWDC 2014 and released in September 2014, Swift was designed by Chris Lattner and team to replace Objective-C for Apple ecosystem development while maintaining interoperability. Swift combines the best features of C/Objective-C without the constraints of C compatibility, featuring modern syntax, safety features, and high performance through LLVM compilation.
🔬 Core Characteristics
- Type Safe: Strong static typing with type inference prevents type errors at compile time
- Memory Safe: Automatic Reference Counting (ARC) manages memory automatically
- Fast: Compiled via LLVM to native code, often outperforming Objective-C
- Expressive: Clean syntax with modern features like closures, tuples, generics
- Protocol-Oriented: Emphasizes protocol-oriented programming over classical inheritance
- Multi-platform: Runs on iOS, macOS, watchOS, tvOS, Linux, and Windows
- Open Source: Developed openly on GitHub with Apache 2.0 license
📊 Industry Usage
Swift powers 90%+ of new iOS/macOS applications, used by Uber, Airbnb, LinkedIn, and all Apple first-party apps. Ranked in top 10 most loved languages in Stack Overflow Developer Survey (2024). Swift on Server growing with Vapor and Kitura frameworks. Used by 4M+ developers worldwide with 200K+ open source packages. Performance benchmarks show 2.6x faster than Objective-C and 8.4x faster than Python 3.12.
import Foundation
print("🦅 Welcome to Swift Master Track!")
print("Swift Version: \(ProcessInfo.processInfo.operatingSystemVersionString)")
let currentDate = Date()
let formatter = DateFormatter()
formatter.dateStyle = .long
print("Today is: \(formatter.string(from: currentDate))")
struct WelcomeMessage {
let platform: String
let year: Int
func display() -> String {
return "Building for \(platform) in \(year) 🚀"
}
}
let message = WelcomeMessage(platform: "iOS & macOS", year: 2024)
print(message.display())
📱 Swift Basics
🎯 Complete Definition
Swift Basics encompass the fundamental building blocks including variables, constants, data types, operators, and type annotations. Swift uses type inference to deduce types automatically while allowing explicit type annotations for clarity. The language distinguishes between mutable (var) and immutable (let) references, encouraging immutability by default. Swift's type system is strong and static, meaning type checking happens at compile time, preventing many common programming errors.
🏷️ 8 Fundamental Data Types
- Int: Signed integers (Int8, Int16, Int32, Int64, Int) - platform dependent size
- UInt: Unsigned integers (UInt8, UInt16, UInt32, UInt64, UInt)
- Float: 32-bit floating point numbers (6-9 decimal digits precision)
- Double: 64-bit floating point numbers (15-17 decimal digits precision, default)
- Bool: Boolean values (true/false, not 0/1 like in C)
- String: Unicode-compliant text with value semantics
- Character: Single Unicode character
- Optional: Special type representing either a value or nil
🔧 Advanced Features
Swift supports type aliases for creating alternative names for existing types, tuples for grouping multiple values, and type casting with as, as?, as!. The language uses Unicode-compliant identifiers allowing emoji and non-Latin characters in variable names. String interpolation provides clean syntax for embedding values in strings. Semicolons are optional except when multiple statements appear on one line.
// Variables (mutable) vs Constants (immutable)
var userName = "CodeOrbitPro" // Type inferred as String
let userId = 12345 // Constant - cannot be changed
var score: Double = 95.5 // Explicit type annotation
var isActive: Bool = true // Boolean type
// Type inference in action
let pi = 3.14159 // Inferred as Double (not Float)
let maxScore = 100 // Inferred as Int
let message = "Hello, \(userName)!" // String interpolation
// Multiple assignment with tuples
let (x, y, z) = (1, 2, 3)
print("Coordinates: \(x), \(y), \(z)")
// Type aliases
typealias StudentID = Int
typealias CompletionHandler = (Bool, String) -> Void
let studentId: StudentID = 54321
print("Student ID: \(studentId)")
// String operations
let greeting = "Welcome to Swift"
print(greeting.count) // Character count
print(greeting.uppercased()) // Uppercase conversion
🎯 Optionals
🎯 Complete Definition
Optionals are Swift's solution to representing the absence of a value in a type-safe manner. An optional in Swift is an enumeration with two cases: .none (representing nil) and .some(value) (wrapping a value). This system eliminates null pointer exceptions common in other languages by forcing developers to explicitly handle missing values. Optionals are a generic type written as Type? which is syntactic sugar for Optional. The ! operator forces unwrapping (dangerous), while safe unwrapping methods prevent runtime crashes.
🔍 Optional Handling Techniques
- Optional Binding:
if let and guard let for safe unwrapping
- Nil Coalescing:
?? operator provides default values
- Optional Chaining:
? allows safe property/method access
- Force Unwrapping:
! assumes value exists (crashes if nil)
- Implicitly Unwrapped Optionals:
Type! for values set after initialization
- Optional Mapping:
map() and flatMap() transform optional values
⚡ Advanced Optional Patterns
Swift 5.7 introduced if let shorthand reducing boilerplate. Optional pattern matching works with switch statements. Result builders can handle optional values in DSLs. The @OptionalType attribute marks protocol requirements as optional. Key paths support optional chaining. Swift's compiler ensures optionals are properly handled through exhaustive checking, making "unexpectedly found nil" errors explicit rather than silent failures.
// Optional declaration
var optionalString: String? = "Hello"
var nilString: String? = nil
// Optional binding (safe unwrapping)
if let unwrappedString = optionalString {
print("String has value: \(unwrappedString)")
} else {
print("String is nil")
}
// Guard statement for early exit
func processUser(name: String?) {
guard let userName = name else {
print("No username provided")
return
}
print("Processing user: \(userName)")
}
// Nil coalescing operator
let displayName = optionalString ?? "Anonymous User"
print("Welcome, \(displayName)!")
// Optional chaining
struct User {
var profile: Profile?
}
struct Profile {
var bio: String?
}
let user = User(profile: Profile(bio: "Swift Developer"))
let bioLength = user.profile?.bio?.count // Optional Int
print("Bio length: \(bioLength ?? 0)")
// Implicitly unwrapped optional (use cautiously)
var forcedString: String! = "I'm guaranteed to have a value"
print(forcedString.uppercased()) // No need to unwrap
// Optional mapping
let numberString: String? = "42"
let number = numberString.map { Int($0) } // Optional>
let flatNumber = numberString.flatMap { Int($0) } // Optional
print("Mapped number: \(flatNumber ?? 0)")
🔀 Control Flow
🎯 Complete Definition
Control flow in Swift determines the execution order of statements and includes conditional statements, loops, and control transfer statements. Swift provides modern control flow constructs with safety features and expressive syntax. Unlike C-based languages, Swift doesn't require parentheses around conditions, and braces are always required even for single-line bodies. The language eliminates common errors like accidental assignment in conditions (= instead of ==) by making assignments non-Bool returning. Swift's control flow is designed to be both safe and expressive.
🏗️ Control Structures
- if-else if-else: Standard conditional branching
- switch-case: Powerful pattern matching with exhaustive checking
- for-in: Iterates over sequences, ranges, and collections
- while/repeat-while: Conditional loops (repeat-while = do-while)
- guard: Early exit condition with required else clause
- range operators:
a...b (closed), a.. (half-open)
- where clauses: Additional conditions in loops and switch cases
⚡ Advanced Control Flow
Swift's switch statements are extremely powerful supporting value binding, tuple matching, type casting patterns, and where clauses. Pattern matching works with if-case-let syntax. Labeled statements allow breaking/continuing specific loops. Fallthrough explicitly continues to next case. #available checks API availability. Control flow constructs work with optionals through optional binding. The compiler performs exhaustiveness checking on switches ensuring all cases are handled.
// If-else statements
let temperature = 25
if temperature > 30 {
print("It's hot! 🔥")
} else if temperature < 10 {
print("It's cold! ❄️")
} else {
print("Perfect weather! 🌤️")
}
// Switch with pattern matching
let point = (2, 0)
switch point {
case (0, 0):
print("Origin")
case (_, 0):
print("On x-axis")
case (0, _):
print("On y-axis")
case (-2...2, -2...2):
print("Inside 4x4 square")
default:
print("Somewhere else")
}
// For-in loops
for number in 1...5 {
print("Number: \(number)")
}
let languages = ["Swift", "Kotlin", "Python"]
for (index, language) in languages.enumerated() {
print("\(index + 1). \(language)")
}
// While loop
var countdown = 3
while countdown > 0 {
print("\(countdown)...")
countdown -= 1
}
print("Launch! 🚀")
// Repeat-while (do-while equivalent)
var attempts = 0
repeat {
print("Attempt \(attempts + 1)")
attempts += 1
} while attempts < 3
// Guard statement for early exit
func login(username: String?, password: String?) -> Bool {
guard let username = username, !username.isEmpty,
let password = password, password.count >= 8 else {
return false
}
// username and password are safely unwrapped here
return true
}
⚙️ Functions
🎯 Complete Definition
Functions in Swift are self-contained chunks of code that perform specific tasks, defined with the func keyword. Swift functions support multiple return values via tuples, parameter labels (external and internal), default parameter values, variadic parameters, and in-out parameters. Functions are first-class citizens meaning they can be assigned to variables, passed as arguments, and returned from other functions. Swift uses a clean, expressive syntax that eliminates much of the verbosity found in Objective-C while maintaining clarity.
🏗️ Function Features
- func keyword: Defines a function with parameters and return type
- Parameter labels: External (argument label) and internal (parameter name)
- Default parameters: Provide default values for parameters
- Variadic parameters: Accept zero or more values of specified type
- In-out parameters: Modify variables passed as arguments
- Function types:
(ParameterTypes) -> ReturnType
- Nested functions: Functions defined inside other functions
⚡ Advanced Function Capabilities
Swift supports function overloading (multiple functions with same name but different parameters). @discardableResult suppresses warnings for unused return values. @autoclosure automatically wraps expressions in closures. @escaping indicates closures that outlive function scope. @inlinable suggests inlining for performance. Functions can have generic parameters making them work with any type. The throws/rethrows keywords enable error propagation. Swift's function syntax balances expressiveness with safety.
// Basic function
func greet(person: String) -> String {
return "Hello, \(person)!"
}
print(greet(person: "CodeOrbitPro"))
// Multiple return values via tuple
func minMax(array: [Int]) -> (min: Int, max: Int)? {
guard !array.isEmpty else { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..
currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
print("Min: \(bounds.min), Max: \(bounds.max)")
}
// Parameter labels
func calculateArea(for width: Double, and height: Double) -> Double {
return width * height
}
print(calculateArea(for: 5.0, and: 10.0))
// Default parameters
func increment(number: Int, by amount: Int = 1) -> Int {
return number + amount
}
print(increment(number: 5)) // Uses default (6)
print(increment(number: 5, by: 3)) // Custom increment (8)
// Variadic parameters
func average(_ numbers: Double...) -> Double {
var total = 0.0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
print(average(1, 2, 3, 4, 5))
// In-out parameters (modify original variable)
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var x = 3
var y = 107
swapTwoInts(&x, &y)
print("x is now \(x), y is now \(y)")
// Function types
let mathFunction: (Int, Int) -> Int = { $0 + $1 }
print("Sum: \(mathFunction(2, 3))")
📦 Collections
🎯 Complete Definition
Collections in Swift are generic containers that store multiple values. Swift provides three primary collection types: Arrays (ordered collections), Sets (unordered unique elements), and Dictionaries (key-value pairs). All Swift collections are value types with copy-on-write optimization, meaning they're copied only when mutated. Collections are generic over their element types using angle bracket syntax Array. Swift's collection API is comprehensive with functional programming methods like map, filter, reduce.
📊 Collection Types
- Array: Ordered, random-access collection, zero-based indexing
- Set: Unordered collection of unique Hashable elements
- Dictionary: Unordered collection of key-value pairs with unique keys
- Range: Represents an interval of values (closed, half-open, one-sided)
- String: Collection of Characters with bidirectional indexing
- Collection protocols: Sequence, Collection, BidirectionalCollection, RandomAccessCollection
⚡ Collection Operations
Swift collections support subscripting for element access, range operators for slicing, and collection algorithms for searching, sorting, and transforming. The Collection protocol provides unified interface. Lazy collections defer computation until needed. Key paths enable type-safe property access. Collections are bridged to Objective-C counterparts (NSArray, NSSet, NSDictionary) when imported. Performance characteristics: Array O(1) random access, Set O(1) average membership test, Dictionary O(1) average key lookup.
// Arrays
var programmingLanguages = ["Swift", "Kotlin", "Python"]
programmingLanguages.append("JavaScript")
programmingLanguages.insert("Rust", at: 1)
print("Languages: \(programmingLanguages)")
print("First language: \(programmingLanguages.first ?? "")")
print("Count: \(programmingLanguages.count)")
// Array operations
let numbers = [1, 2, 3, 4, 5]
let doubled = numbers.map { $0 * 2 }
let evenNumbers = numbers.filter { $0 % 2 == 0 }
let sum = numbers.reduce(0, +)
print("Doubled: \(doubled)")
print("Even: \(evenNumbers)")
print("Sum: \(sum)")
// Sets (unique, unordered)
var programmingSet: Set = ["Swift", "Python", "Java"]
programmingSet.insert("Kotlin")
programmingSet.insert("Swift") // Won't add duplicate
print("Set: \(programmingSet)")
let swiftSet: Set = ["Swift", "iOS", "Xcode"]
let pythonSet: Set = ["Python", "Django", "Data Science"]
print("Union: \(swiftSet.union(pythonSet))")
print("Intersection: \(swiftSet.intersection(pythonSet))")
// Dictionaries
var userScores = ["Alice": 95, "Bob": 87, "Charlie": 92]
userScores["David"] = 88 // Add new entry
userScores["Alice"] = 96 // Update existing
for (name, score) in userScores {
print("\(name): \(score)")
}
// Safe dictionary access
if let bobScore = userScores["Bob"] {
print("Bob's score: \(bobScore)")
}
// Default values
let eveScore = userScores["Eve", default: 0]
print("Eve's score: \(eveScore)")
// Collection transformations
let scores = [85, 92, 78, 95, 88]
let scoreDescriptions = scores.map { score -> String in
switch score {
case 90...100: return "\(score): Excellent ⭐⭐⭐"
case 80..<90: return "\(score): Good ⭐⭐"
case 70..<80: return "\(score): Fair ⭐"
default: return "\(score): Needs improvement"
}
}
print(scoreDescriptions)
🎚️ Enumerations
🎯 Complete Definition
Enumerations (enums) in Swift are first-class types that define a common type for a group of related values. Unlike C enums which are essentially integers, Swift enums are much more powerful: they can have associated values, methods, computed properties, initializers, and can conform to protocols. Enums are value types and support pattern matching. Each enum case is a full-fledged value, not just an integer constant. Swift enums don't have an implicit raw value (unless explicitly specified), preventing common errors where enum values are used interchangeably with integers.
🏗️ Enum Features
- Case values: Distinct members of the enumeration
- Raw values: Pre-populated values (String, Int, Float, Character)
- Associated values: Additional data attached to enum cases
- Methods: Functions defined within enums
- Computed properties: Properties that calculate values
- Initializers: Custom initialization logic
- Protocol conformance: Enums can conform to protocols
⚡ Advanced Enum Capabilities
Swift enums support recursive enumerations with indirect keyword for cases that have associated values of the enum type itself. CaseIterable protocol provides automatic allCases collection. Enums can have stored properties through associated values. Pattern matching with switch statements exhaustively handles all cases. RawRepresentable protocol enables conversion between raw values and cases. Enums are hashable by default when all associated values are hashable. OptionSet protocol enables bitmask-style flags.
// Basic enum
enum CompassPoint {
case north
case south
case east
case west
}
var direction = CompassPoint.north
direction = .east // Type inference allows shorthand
// Switch on enum
switch direction {
case .north:
print("Heading north 🧭")
case .south:
print("Heading south")
case .east:
print("Heading east")
case .west:
print("Heading west")
}
// Raw values (String, Int, Character)
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
let earth = Planet.earth
print("Earth is planet #\(earth.rawValue)")
// Associated values
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
let productBarcode = Barcode.upc(8, 85909, 51226, 3)
let siteBarcode = Barcode.qrCode("https://codeorbitpro.com")
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem)-\(manufacturer)-\(product)-\(check)")
case .qrCode(let productCode):
print("QR code: \(productCode)")
}
// Methods in enums
enum TrafficLight {
case red, yellow, green
func description() -> String {
switch self {
case .red: return "Stop 🛑"
case .yellow: return "Caution ⚠️"
case .green: return "Go ✅"
}
}
mutating func next() {
switch self {
case .red: self = .green
case .yellow: self = .red
case .green: self = .yellow
}
}
}
var light = TrafficLight.red
print(light.description())
light.next()
print("Next light: \(light.description())")
// CaseIterable for iteration
enum Beverage: CaseIterable {
case coffee, tea, juice, water
}
print("Available beverages:")
for beverage in Beverage.allCases {
print("- \(beverage)")
}
// Recursive enum
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
let expression = ArithmeticExpression.addition(
.number(5),
.multiplication(.number(2), .number(3))
)
func evaluate(_ expression: ArithmeticExpression) -> Int {
switch expression {
case let .number(value):
return value
case let .addition(left, right):
return evaluate(left) + evaluate(right)
case let .multiplication(left, right):
return evaluate(left) * evaluate(right)
}
}
print("Expression result: \(evaluate(expression))") // 5 + (2 * 3) = 11
🏗️ Structs & Classes
🎯 Complete Definition
Structs and Classes in Swift are general-purpose, flexible constructs that become the building blocks of programs. Both can define properties to store values and methods to provide functionality. The key difference is that structs are value types (copied when assigned or passed) while classes are reference types (share a single instance). Structs don't support inheritance, while classes do. Swift encourages using structs by default due to their safety benefits - no unexpected sharing, thread-safe by default, and easier to reason about. Classes are used when reference semantics are needed or when inheritance is required.
🔬 Key Differences
- Type: Structs = Value type, Classes = Reference type
- Inheritance: Structs = No, Classes = Single inheritance
- Deinitializer: Structs = No, Classes = Yes (deinit)
- ARC: Structs = No (stored on stack), Classes = Yes (managed by ARC)
- Identity operators: Structs = No, Classes = Yes (===, !==)
- Default memberwise initializer: Structs = Yes, Classes = No
🏗️ Common Features
Both support properties (stored, computed, lazy), methods, initializers, subscripts, and protocol conformance. Both can be extended with extensions. Both support property observers (willSet, didSet). Both can have type properties/methods (static/class). Swift uses automatic reference counting for classes. Structs get memberwise initializers automatically. Both support access control (private, fileprivate, internal, public, open).
// Struct definition
struct Resolution {
var width = 0
var height = 0
// Computed property
var aspectRatio: Double {
return Double(width) / Double(height)
}
// Method
func description() -> String {
return "\(width)x\(height)"
}
}
// Class definition
class VideoMode {
var resolution = Resolution()
var frameRate = 0.0
var name: String?
// Property observers
var duration: Double = 0 {
willSet {
print("About to set duration to \(newValue)")
}
didSet {
print("Duration changed from \(oldValue) to \(duration)")
}
}
// Initializer
init(resolution: Resolution, frameRate: Double, name: String?) {
self.resolution = resolution
self.frameRate = frameRate
self.name = name
}
// Deinitializer (classes only)
deinit {
print("VideoMode instance is being deallocated")
}
}
// Value type behavior (struct)
var hd = Resolution(width: 1920, height: 1080)
var cinema = hd // This creates a COPY
cinema.width = 2048
print("HD width: \(hd.width)") // 1920 (unchanged)
print("Cinema width: \(cinema.width)") // 2048
// Reference type behavior (class)
let video = VideoMode(resolution: hd, frameRate: 60.0, name: "Sample")
let alsoVideo = video // This shares the SAME instance
alsoVideo.frameRate = 30.0
print("Video frameRate: \(video.frameRate)") // 30.0 (changed)
print("AlsoVideo frameRate: \(alsoVideo.frameRate)") // 30.0
// Identity operators (classes only)
if video === alsoVideo {
print("video and alsoVideo refer to the same instance")
}
// Inheritance
class Animal {
var name: String
init(name: String) {
self.name = name
}
func makeSound() -> String {
return "Some generic animal sound"
}
}
class Dog: Animal {
var breed: String
init(name: String, breed: String) {
self.breed = breed
super.init(name: name)
}
override func makeSound() -> String {
return "Woof! 🐕"
}
// Final method cannot be overridden
final func fetch() -> String {
return "\(name) fetches the ball!"
}
}
let myDog = Dog(name: "Buddy", breed: "Golden Retriever")
print(myDog.makeSound())
print(myDog.fetch())
📜 Protocols
🎯 Complete Definition
Protocols in Swift define a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. Protocols are similar to interfaces in other languages but more powerful. A protocol can be adopted by any class, struct, or enum to provide an actual implementation of those requirements. Swift is a protocol-oriented programming language - protocols are used extensively throughout Swift's standard library and are central to many design patterns. Protocols enable polymorphism without inheritance, composition over inheritance, and allow value types (structs, enums) to participate in polymorphic behavior.
🏗️ Protocol Requirements
- Property requirements: var properties with get/set specifications
- Method requirements: Instance and type methods
- Mutating methods: For value types that need to modify self
- Initializer requirements: Required initializers
- Subscript requirements: For accessing elements by index/key
- Associated types: Generic placeholders within protocols
⚡ Advanced Protocol Features
Protocols support protocol inheritance (multiple inheritance allowed). Protocol composition combines multiple protocols. Conditional conformance allows types to conform to protocols only under certain conditions. Protocol extensions provide default implementations. @objc protocols enable Objective-C interoperability. Existential types (Protocol) enable heterogeneous collections. Self requirements enable returning/conforming to the adopting type. Opaque types (some Protocol) hide concrete types while preserving type identity.
// Basic protocol
protocol Vehicle {
var numberOfWheels: Int { get }
var maxSpeed: Double { get }
func start()
func stop()
func description() -> String
}
// Protocol with mutating method
protocol Toggleable {
mutating func toggle()
}
// Protocol inheritance
protocol ElectricVehicle: Vehicle {
var batteryCapacity: Double { get }
func charge(to percentage: Double)
}
// Protocol adoption by struct
struct Car: Vehicle {
let numberOfWheels: Int = 4
let maxSpeed: Double = 200.0
func start() {
print("Car engine started 🚗")
}
func stop() {
print("Car stopped")
}
func description() -> String {
return "Car with \(numberOfWheels) wheels, max speed: \(maxSpeed) km/h"
}
}
// Protocol adoption by class
class Bicycle: Vehicle, Toggleable {
var numberOfWheels: Int = 2
var maxSpeed: Double = 30.0
var isLocked: Bool = false
func start() {
print("Bicycle ready to ride 🚲")
}
func stop() {
print("Bicycle stopped")
}
func description() -> String {
return "Bicycle with \(numberWheels) wheels"
}
// Mutating method (struct would need mutating keyword)
func toggle() {
isLocked.toggle()
print("Bicycle \(isLocked ? "locked" : "unlocked")")
}
}
// Using protocols
let myCar = Car()
let myBike = Bicycle()
let vehicles: [Vehicle] = [myCar, myBike]
for vehicle in vehicles {
print(vehicle.description())
vehicle.start()
}
// Protocol extensions
extension Vehicle {
func honk() {
print("Beep beep! 🔊")
}
// Default implementation
func description() -> String {
return "Vehicle with \(numberOfWheels) wheels"
}
}
myCar.honk()
// Protocol with associated type (generic protocol)
protocol Container {
associatedtype Item
var count: Int { get }
mutating func append(_ item: Item)
subscript(i: Int) -> Item { get }
}
struct IntStack: Container {
typealias Item = Int
private var items: [Item] = []
var count: Int { items.count }
mutating func append(_ item: Item) {
items.append(item)
}
subscript(i: Int) -> Item {
return items[i]
}
}
// Protocol composition
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Aged {
let name: String
let age: Int
}
func wishHappyBirthday(to celebrant: Named & Aged) {
print("Happy birthday, \(celebrant.name), you're \(celebrant.age)! 🎂")
}
let birthdayPerson = Person(name: "CodeOrbitPro", age: 25)
wishHappyBirthday(to: birthdayPerson)
// Conditional protocol conformance
extension Array: Container where Element: Equatable {
typealias Item = Element
mutating func append(_ item: Item) {
self.append(item)
}
}
🔤 Generics
🎯 Complete Definition
Generics in Swift enable you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. Generics are one of Swift's most powerful features, used extensively throughout the standard library. They allow you to write code that avoids duplication while maintaining type safety. Generic code uses type parameters (placeholder types) that are specified when the code is used. Swift's generics system is similar to C++ templates but with type safety and without code bloat - generic code is compiled once and works with any type that meets the constraints.
🏗️ Generic Constructs
- Generic Functions: Functions that work with any type
- Generic Types: Classes, structs, enums that work with any type
- Type Parameters: Placeholder types in angle brackets
- Type Constraints: Require type parameters to conform to protocols or inherit from classes
- Associated Types: Generic placeholders in protocols
- Generic Where Clauses: Additional requirements on associated types
⚡ Advanced Generic Features
Swift supports opaque types (some Protocol) that hide concrete return types while preserving type identity. Existential types (any Protocol) enable heterogeneous collections. Primary associated types (Swift 5.7) simplify generic constraints. Type erasure patterns hide concrete types. Generic subscripts work with any type. Recursive generic constraints enable complex type relationships. The Swift compiler performs type inference for generic parameters at call sites. Generics enable polymorphism without inheritance.
// Generic function
func swapTwoValues(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
var string1 = "hello"
var string2 = "world"
swapTwoValues(&string1, &string2)
print("string1 is now \(string1), string2 is now \(string2)")
var int1 = 3
var int2 = 107
swapTwoValues(&int1, &int2)
print("int1 is now \(int1), int2 is now \(int2)")
// Generic type
struct Stack {
private var items: [Element] = []
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element? {
return items.popLast()
}
func peek() -> Element? {
return items.last
}
var isEmpty: Bool {
return items.isEmpty
}
var count: Int {
return items.count
}
}
// Using generic type
var intStack = Stack()
intStack.push(1)
intStack.push(2)
intStack.push(3)
print("Popped: \(intStack.pop() ?? 0)") // 3
var stringStack = Stack()
stringStack.push("Swift")
stringStack.push("Generics")
print("Top item: \(stringStack.peek() ?? "")") // "Generics"
// Type constraints
func findIndex(of valueToFind: T, in array: [T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25, 9.3])
let stringIndex = findIndex(of: "Swift", in: ["Objective-C", "Swift", "Kotlin"])
print("Double index: \(doubleIndex ?? -1)")
print("String index: \(stringIndex ?? -1)")
// Multiple constraints
protocol Container {
associatedtype Item
var count: Int { get }
mutating func append(_ item: Item)
subscript(i: Int) -> Item { get }
}
func allItemsMatch
(_ container1: C1, _ container2: C2) -> Bool
where C1.Item == C2.Item, C1.Item: Equatable {
if container1.count != container2.count {
return false
}
for i in 0..(indices: Indices) -> [Element]
where Indices.Iterator.Element == Int {
var result: [Element] = []
for index in indices {
if index < items.count {
result.append(items[index])
}
}
return result
}
}
// Using generic subscript
intStack.push(10)
intStack.push(20)
intStack.push(30)
let selectedItems = intStack[[0, 2]]
print("Selected items: \(selectedItems)") // [10, 30]
// Opaque return types (Swift 5.1+)
protocol Shape {
func draw() -> String
}
struct Square: Shape {
var size: Int
func draw() -> String {
return "Square with size \(size)"
}
}
struct FlippedShape: Shape {
var shape: T
func draw() -> String {
return "Flipped \(shape.draw())"
}
}
// Returns some Shape (opaque type)
func makeTrapezoid() -> some Shape {
let top = Square(size: 2)
let middle = Square(size: 4)
let bottom = Square(size: 6)
// Combine shapes...
return FlippedShape(shape: top)
}
let trapezoid = makeTrapezoid()
print(trapezoid.draw())
⚠️ Error Handling
🎯 Complete Definition
Error handling in Swift provides a way to respond to and recover from error conditions in programs. Swift uses a type-safe error handling model that resembles exception handling in other languages but is both more explicit and integrated with the type system. Errors are represented by values of types that conform to the Error protocol. Four ways to handle errors in Swift: 1) Propagate errors using throws, 2) Handle with do-catch, 3) Convert to optional with try?, 4) Assert error won't occur with try!. Swift's error handling doesn't involve unwinding the call stack (unlike exceptions in some languages), making it more performant.
🏗️ Error Handling Constructs
- Error protocol: Types that can represent error conditions
- throwing functions: Functions that can throw errors
- do-catch statements: Handle specific error patterns
- try keyword: Call throwing functions
- try? and try!: Convert errors to optionals or force unwrap
- defer statements: Cleanup code that runs regardless of errors
- Result type: Alternative error handling pattern
⚡ Advanced Error Handling
Swift supports rethrows for functions that only throw if their closure parameters throw. Local error propagation allows catching and rethrowing different errors. Error chaining preserves original error context. Custom error types can include additional data. Error localization via LocalizedError protocol. Recoverable errors patterns for user-facing errors. The Result type (Swift 5) provides functional error handling alternative. Async/await integrates with error handling seamlessly. Swift errors are not used for control flow (unlike some exception systems).
// Defining error types
enum NetworkError: Error {
case invalidURL
case noConnection
case timeout(seconds: Int)
case serverError(statusCode: Int)
case decodingError(message: String)
}
enum ValidationError: Error {
case emptyField(fieldName: String)
case invalidEmail
case passwordTooShort(minLength: Int)
case ageRestriction(minimumAge: Int)
}
// Throwing function
func fetchData(from urlString: String) throws -> String {
guard !urlString.isEmpty else {
throw NetworkError.invalidURL
}
guard urlString.hasPrefix("http") else {
throw NetworkError.invalidURL
}
// Simulate network conditions
let randomNumber = Int.random(in: 1...10)
switch randomNumber {
case 1...3:
throw NetworkError.noConnection
case 4...5:
throw NetworkError.timeout(seconds: 30)
case 6...7:
throw NetworkError.serverError(statusCode: 500)
default:
return "Sample data from \(urlString)"
}
}
// do-catch error handling
func loadUserData() {
do {
let data = try fetchData(from: "https://api.example.com")
print("Success: \(data)")
// Multiple throwing calls in same do block
let moreData = try fetchData(from: "https://api2.example.com")
print("More data: \(moreData)")
} catch NetworkError.invalidURL {
print("Error: Invalid URL provided")
} catch NetworkError.noConnection {
print("Error: No internet connection")
} catch NetworkError.timeout(let seconds) {
print("Error: Request timed out after \(seconds) seconds")
} catch NetworkError.serverError(let statusCode) {
print("Error: Server responded with status code \(statusCode)")
} catch {
print("An unexpected error occurred: \(error)")
}
}
loadUserData()
// try? converts errors to optionals
let optionalData = try? fetchData(from: "https://bad-url")
if let data = optionalData {
print("Got data: \(data)")
} else {
print("Failed to get data (error converted to nil)")
}
// try! asserts error won't occur (crashes if it does)
// let forcedData = try! fetchData(from: "https://api.example.com") // Dangerous!
// defer statement for cleanup
func processFile(filename: String) throws {
print("Opening file: \(filename)")
defer {
print("Closing file: \(filename)")
// This runs no matter how the function exits
}
defer {
print("First defer runs last (LIFO)")
}
let data = try fetchData(from: "https://files.example.com/\(filename)")
print("Processing: \(data)")
// Even if error thrown above, defer still runs
}
// Using Result type for error handling
func validateUser(email: String, password: String) -> Result {
guard !email.isEmpty else {
return .failure(.emptyField(fieldName: "email"))
}
guard email.contains("@") && email.contains(".") else {
return .failure(.invalidEmail)
}
guard password.count >= 8 else {
return .failure(.passwordTooShort(minLength: 8))
}
return .success("User validated successfully")
}
// Handling Result
let validationResult = validateUser(email: "user@example.com", password: "weak")
switch validationResult {
case .success(let message):
print("Validation success: \(message)")
case .failure(let error):
switch error {
case .emptyField(let field):
print("Please fill in the \(field) field")
case .invalidEmail:
print("Please enter a valid email address")
case .passwordTooShort(let minLength):
print("Password must be at least \(minLength) characters")
default:
print("Validation failed")
}
}
// Rethrowing functions
func processWithRetry(attempts: Int, operation: () throws -> String) rethrows -> String {
for attempt in 1...attempts {
do {
return try operation()
} catch {
print("Attempt \(attempt) failed: \(error)")
if attempt == attempts {
throw error
}
}
}
fatalError("Should never reach here")
}
// Using rethrows
do {
let result = try processWithRetry(attempts: 3) {
return try fetchData(from: "https://api.example.com")
}
print("Final result: \(result)")
} catch {
print("All attempts failed: \(error)")
}
🌀 Async/Await
🎯 Complete Definition
Async/await in Swift (introduced in Swift 5.5) is a modern concurrency model that provides a simple, safe way to write asynchronous code. It allows you to write asynchronous code that looks and behaves like synchronous code, eliminating "callback hell" and making concurrent programming more accessible. The model is built on structured concurrency principles ensuring tasks are properly managed and don't leak. Async/await works with Swift's existing error handling model (throws/try) and integrates with the actor model for data race safety. Under the hood, it uses continuations and the cooperative thread pool.
🏗️ Async/Await Components
- async: Marks a function as asynchronous
- await: Suspends execution until async operation completes
Task: Unit of concurrent execution
- async let: Concurrently binds async expression results
- TaskGroup: Manages dynamic number of child tasks
- actors: Reference types that protect mutable state
- @MainActor: Ensures code runs on main thread
⚡ Advanced Concurrency Features
Swift concurrency supports structured task hierarchies where parent tasks manage child tasks. Task cancellation propagates through task trees. Task priorities influence execution order. Async sequences enable iterating over asynchronous streams. Async properties and subscripts are supported. Sendable protocol ensures safe cross-actor value passing. Global actors provide custom execution contexts. The system uses cooperative cancellation requiring tasks to check cancellation status. Integration with Objective-C completion handlers via continuations.
// Basic async function
func fetchUserProfile(userId: Int) async throws -> String {
// Simulate network delay
try await Task.sleep(nanoseconds: 1_000_000_000) // 1 second
if userId == 1 {
return "User Profile: CodeOrbitPro (Swift Developer)"
} else {
throw NetworkError.serverError(statusCode: 404)
}
}
// Async function without throwing
func calculateStatistics(scores: [Int]) async -> (min: Int, max: Int, average: Double) {
// Simulate heavy computation
await Task.yield() // Yield to allow other tasks to run
guard !scores.isEmpty else {
return (0, 0, 0.0)
}
let min = scores.min() ?? 0
let max = scores.max() ?? 0
let average = Double(scores.reduce(0, +)) / Double(scores.count)
return (min, max, average)
}
// Using async/await
Task {
do {
let profile = try await fetchUserProfile(userId: 1)
print("Fetched: \(profile)")
let scores = [85, 92, 78, 95, 88]
let stats = await calculateStatistics(scores: scores)
print("Stats - Min: \(stats.min), Max: \(stats.max), Avg: \(stats.average)")
} catch {
print("Error: \(error)")
}
}
// Concurrent execution with async let
func fetchMultipleData() async {
async let userData = fetchUserProfile(userId: 1)
async let productData = fetchProductInfo(productId: 42)
async let settings = loadUserSettings()
do {
// All three fetches run concurrently
let (user, product, settings) = try await (userData, productData, settings)
print("User: \(user), Product: \(product), Settings: \(settings)")
} catch {
print("One of the fetches failed: \(error)")
}
}
// Helper functions for above example
func fetchProductInfo(productId: Int) async throws -> String {
try await Task.sleep(nanoseconds: 500_000_000)
return "Product #\(productId): Swift Programming Guide"
}
func loadUserSettings() async throws -> String {
try await Task.sleep(nanoseconds: 300_000_000)
return "Settings: Dark Mode, Notifications Enabled"
}
// Task groups for dynamic concurrency
func downloadMultipleFiles(urls: [String]) async throws -> [String] {
try await withThrowingTaskGroup(of: String.self) { group in
var downloadedFiles: [String] = []
// Add child tasks for each URL
for url in urls {
group.addTask {
try await downloadFile(from: url)
}
}
// Collect results as they complete
for try await file in group {
downloadedFiles.append(file)
print("Downloaded: \(file)")
}
return downloadedFiles
}
}
// Helper for download
func downloadFile(from url: String) async throws -> String {
try await Task.sleep(nanoseconds: UInt64.random(in: 500_000_000...2_000_000_000))
return "File from \(url)"
}
// Actor for shared mutable state
actor BankAccount {
private var balance: Double
private let accountNumber: String
init(accountNumber: String, initialBalance: Double) {
self.accountNumber = accountNumber
self.balance = initialBalance
}
func deposit(amount: Double) {
balance += amount
print("Deposited \(amount). New balance: \(balance)")
}
func withdraw(amount: Double) -> Bool {
if amount <= balance {
balance -= amount
print("Withdrew \(amount). New balance: \(balance)")
return true
} else {
print("Insufficient funds. Balance: \(balance), Attempted: \(amount)")
return false
}
}
func getBalance() -> Double {
return balance
}
}
// Using actor
Task {
let account = BankAccount(accountNumber: "123456", initialBalance: 1000.0)
// Must use await to interact with actor
await account.deposit(amount: 500.0)
let success = await account.withdraw(amount: 200.0)
let currentBalance = await account.getBalance()
print("Withdrawal successful: \(success), Current balance: \(currentBalance)")
}
// @MainActor for UI updates
@MainActor
class UserViewModel: ObservableObject {
@Published var userName: String = ""
@Published var isLoading: Bool = false
func loadUser() async {
isLoading = true
// This runs on main thread automatically
do {
let profile = try await fetchUserProfile(userId: 1)
userName = profile
} catch {
userName = "Error loading user"
}
isLoading = false
}
}
// Async properties and subscripts
struct AsyncDataLoader {
subscript(index: Int) async throws -> String {
try await Task.sleep(nanoseconds: 100_000_000)
return "Data at index \(index)"
}
var firstItem: String {
get async throws {
try await self[0]
}
}
}
// Using async properties
Task {
let loader = AsyncDataLoader()
let first = try await loader.firstItem
print("First item: \(first)")
let third = try await loader[2]
print("Third item: \(third)")
}
💾 Memory Management
🎯 Complete Definition
Memory management in Swift is primarily handled through Automatic Reference Counting (ARC), which automatically tracks and manages your app's memory usage. ARC works by counting how many references exist to each class instance (reference type). When the reference count reaches zero, ARC deallocates the instance and frees its memory. For value types (structs, enums), memory is managed automatically on the stack or inline within other types. Swift's memory management is deterministic and predictable - deallocation happens immediately when the last reference is removed, unlike garbage collection which runs at non-deterministic intervals.
🔧 ARC Mechanisms
- Strong references: Default reference type, increments reference count
- Weak references: Don't keep referenced object alive, become nil when object deallocates
Unowned references: Like weak but assumed to always have value, cause crash if accessed after deallocation
- Reference cycles: When two objects hold strong references to each other
- Weak/Unowned breaking cycles: Using weak/unowned to prevent memory leaks
- Capture lists: Specify how values are captured in closures
⚡ Advanced Memory Features
Swift provides unowned(unsafe) for performance-critical code (no runtime checks). @unchecked Sendable for manually managed thread safety. withExtendedLifetime() extends object lifetime. withUnsafePointer() for low-level memory access. MemoryLayout type queries size/alignment/strides. Unsafe types (UnsafePointer, UnsafeBufferPointer) for C interop and performance. Copy-on-write optimization for value types. @autoclosure can affect memory behavior. The Swift runtime uses side tables for weak reference management. Actors provide data race safety for concurrent access.
// ARC Basics
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Weak reference to avoid cycle
init(unit: String) {
self.unit = unit
print("Apartment \(unit) is being initialized")
}
deinit {
print("Apartment \(unit) is being deinitialized")
}
}
// Strong reference cycle example
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john // Weak reference, doesn't create cycle
// When we nil these, both deallocate
john = nil // Prints: "John Appleseed is being deinitialized"
unit4A = nil // Prints: "Apartment 4A is being deinitialized"
// Strong reference cycle (problematic)
class Customer {
let name: String
var creditCard: CreditCard? // Strong reference
init(name: String) {
self.name = name
}
deinit {
print("\(name) is being deinitialized")
}
}
class CreditCard {
let number: String
unowned let customer: Customer // Unowned reference (assumes customer exists longer)
init(number: String, customer: Customer) {
self.number = number
self.customer = customer
}
deinit {
print("Card #\(number) is being deinitialized")
}
}
var customer: Customer? = Customer(name: "Jane Doe")
customer!.creditCard = CreditCard(number: "1234-5678-9012-3456", customer: customer!)
// Both deallocate properly (no cycle due to unowned)
customer = nil // Prints both deinitialization messages
// Closure capture lists
class HTMLElement {
let name: String
let text: String?
// Closure with strong reference to self
lazy var asHTML: () -> String = { [weak self] in
guard let self = self else { return "" }
if let text = self.text {
return "<\(self.name)>\(text)\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "Hello, Swift!")
print(paragraph!.asHTML())
paragraph = nil // Deallocates properly thanks to [weak self]
// Unowned vs Weak
class Country {
let name: String
var capitalCity: City! // Implicitly unwrapped optional
init(name: String, capitalName: String) {
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
}
class City {
let name: String
unowned let country: Country // Country will exist as long as City
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
let country = Country(name: "Canada", capitalName: "Ottawa")
print("\(country.name)'s capital is \(country.capitalCity.name)")
// MemoryLayout for type information
print("MemoryLayout
.size: \(MemoryLayout.size)") // 8 on 64-bit
print("MemoryLayout.alignment: \(MemoryLayout.alignment)") // 8
print("MemoryLayout.stride: \(MemoryLayout.stride)") // 8
struct Point3D {
var x, y, z: Double
}
print("MemoryLayout.size: \(MemoryLayout.size)") // 24 (3 * 8)
print("MemoryLayout.stride: \(MemoryLayout.stride)") // 24
// Unsafe memory operations (advanced)
let count = 3
let pointer = UnsafeMutablePointer.allocate(capacity: count)
pointer.initialize(repeating: 0, count: count)
pointer[0] = 10
pointer[1] = 20
pointer[2] = 30
// Convert to buffer for safer access
let buffer = UnsafeBufferPointer(start: pointer, count: count)
for (index, value) in buffer.enumerated() {
print("Element \(index): \(value)")
}
// Clean up
pointer.deallocate()
// Copy-on-write demonstration
struct ImageData {
private var _data: [UInt8]
init(data: [UInt8]) {
_data = data
}
// Copy-on-write: Only copy when mutated
mutating func modifyPixel(at index: Int, value: UInt8) {
// Ensure we have a unique copy before modifying
if !isKnownUniquelyReferenced(&_data) {
_data = _data.copy()
}
_data[index] = value
}
var data: [UInt8] {
return _data
}
}
var image1 = ImageData(data: [0, 128, 255])
var image2 = image1 // Shares underlying array initially
image2.modifyPixel(at: 0, value: 255) // Now makes a copy
print("Image1: \(image1.data), Image2: \(image2.data)")
⚡ Advanced Swift
🎯 Complete Definition
Advanced Swift encompasses the sophisticated language features and patterns that distinguish expert Swift development. This includes metaprogramming capabilities, advanced type system features, performance optimization techniques, and interoperability patterns. Swift's advanced features enable building high-performance, type-safe, and expressive systems while maintaining safety guarantees. These features include property wrappers, result builders, dynamic member lookup, key paths, and more. Advanced Swift techniques leverage the full power of Swift's type system while maintaining the language's core principles of safety, clarity, and performance.
🔬 Advanced Features
- Property Wrappers: Reusable property behavior abstraction
- Result Builders: Domain-specific languages for declarative UI
- Dynamic Member Lookup: Runtime property/method access
- Key Paths: Type-safe references to properties
- Custom Operators: Define new operators with custom precedence
- @autoclosure: Automatically wrap expressions in closures
- @inlinable: Suggest function inlining to compiler
- #available: Platform/version availability checking
⚡ Cutting-Edge Swift
Swift 5.9+ introduces macros for code generation at compile time. Parameter packs enable variable generic arity. Non-copyable types prevent copying for resource management. Borrowing/consuming parameters optimize value semantics. Custom actor executors provide fine-grained concurrency control. Observation framework replaces Combine for many use cases. C++ interoperability enables direct C++ calls. The Swift compiler continues to evolve with ownership model improvements, whole module optimization, and diagnostic enhancements.
// Property Wrappers
@propertyWrapper
struct Clamped
{
private var value: T
private let range: ClosedRange
var wrappedValue: T {
get { value }
set { value = min(max(range.lowerBound, newValue), range.upperBound) }
}
init(wrappedValue: T, _ range: ClosedRange) {
self.range = range
self.value = min(max(range.lowerBound, wrappedValue), range.upperBound)
}
}
struct GameCharacter {
@Clamped(0...100) var health: Int = 100
@Clamped(0...100) var mana: Int = 50
}
var character = GameCharacter()
character.health = 150 // Clamped to 100
character.mana = -10 // Clamped to 0
print("Health: \(character.health), Mana: \(character.mana)")
// Result Builders (Domain Specific Languages)
@resultBuilder
struct HTMLBuilder {
static func buildBlock(_ components: String...) -> String {
return components.joined(separator: "\n")
}
static func buildArray(_ components: [String]) -> String {
return components.joined(separator: "\n")
}
static func buildOptional(_ component: String?) -> String {
return component ?? ""
}
static func buildEither(first component: String) -> String {
return component
}
static func buildEither(second component: String) -> String {
return component
}
}
@HTMLBuilder
func makePage(title: String, showHeader: Bool) -> String {
""
"\(title)"
""
if showHeader {
""
}
""
"Welcome to our site!
"
""
for item in ["Home", "About", "Contact"] {
"\(item)"
}
""
""
}
let page = makePage(title: "CodeOrbitPro", showHeader: true)
print("Generated HTML page:\n\(page)")
// Dynamic Member Lookup
@dynamicMemberLookup
struct DynamicObject {
private var storage: [String: Any] = [:]
subscript(dynamicMember member: String) -> Any? {
get { storage[member] }
set { storage[member] = newValue }
}
}
var obj = DynamicObject()
obj.name = "Swift" // Dynamically creates property
obj.version = 5.9
obj.isAwesome = true
print("Object: \(obj.name ?? ""), Version: \(obj.version ?? 0)")
// Key Paths
struct Student {
let name: String
var grade: Double
var passed: Bool { grade >= 60.0 }
}
let students = [
Student(name: "Alice", grade: 95.0),
Student(name: "Bob", grade: 58.5),
Student(name: "Charlie", grade: 72.0)
]
// Sort by grade using key path
let sortedByGrade = students.sorted(by: \.grade)
print("Sorted by grade: \(sortedByGrade.map { $0.name })")
// Map to names using key path
let names = students.map(\.name)
print("Names: \(names)")
// Filter by passed using key path
let passingStudents = students.filter(\.passed)
print("Passing students: \(passingStudents.count)")
// Custom Operators
infix operator ^^: ExponentiationPrecedence
precedencegroup ExponentiationPrecedence {
higherThan: MultiplicationPrecedence
associativity: right
}
func ^^(base: Double, exponent: Double) -> Double {
return pow(base, exponent)
}
let result = 2.0 ^^ 3.0 // 8.0
print("2 ^ 3 = \(result)")
// @autoclosure
func assert(_ condition: @autoclosure () -> Bool,
_ message: @autoclosure () -> String = "") {
#if DEBUG
if !condition() {
fatalError("Assertion failed: \(message())")
}
#endif
}
let x = 5
assert(x > 0, "x must be positive") // No need for closure syntax
// #available for API availability
if #available(iOS 15.0, macOS 12.0, *) {
print("Can use iOS 15/macOS 12 APIs")
} else {
print("Need to use older APIs")
}
// Custom string interpolation
extension String.StringInterpolation {
mutating func appendInterpolation(_ value: Date, style: DateFormatter.Style) {
let formatter = DateFormatter()
formatter.dateStyle = style
appendLiteral(formatter.string(from: value))
}
mutating func appendInterpolation(repeat str: String, _ count: Int) {
appendLiteral(String(repeating: str, count: count))
}
}
let today = Date()
print("Today is \(today, style: .long)")
print("Cheers! \(repeat: "🎉", 3)")
// Protocol with primary associated types (Swift 5.7)
protocol Storage {
associatedtype Element
func store(_ item: Element)
func retrieve() -> Element?
}
struct Box- : Storage {
private var item: Item?
func store(_ item: Item) {
// Implementation
}
func retrieve() -> Item? {
return item
}
}
// Opaque parameter types
func processStorage(_ storage: some Storage) {
// Can work with any Storage that stores Ints
}
// Advanced pattern matching
enum AdvancedPattern {
case point(x: Int, y: Int)
case circle(radius: Double)
case rectangle(width: Double, height: Double)
}
let shape = AdvancedPattern.point(x: 10, y: 20)
if case .point(let x, _) = shape, x > 5 {
print("Point with x > 5: \(x)")
}
// Using ~= operator for custom pattern matching
struct RangePattern {
let lower: T
let upper: T
}
func ~= (pattern: RangePattern, value: T) -> Bool {
return value >= pattern.lower && value <= pattern.upper
}
let score = 85
let gradeRange = RangePattern(lower: 90, upper: 100)
switch score {
case gradeRange:
print("Grade: A")
case RangePattern(lower: 80, upper: 89):
print("Grade: B")
case RangePattern(lower: 70, upper: 79):
print("Grade: C")
default:
print("Grade: F")
}