Swift favors value types (structs) over reference types (classes). Closures are everywhere in Swift — they're used for callbacks, higher-order functions, and lazy evaluation.
Structs
SWIFT
// Structs are value types (copied, not shared)
struct Point {
let x: Double
let y: Double
// Computed property
var magnitude: Double {
sqrt(x * x + y * y)
}
// Method
func distance(to other: Point) -> Double {
let dx = x - other.x
let dy = y - other.y
return sqrt(dx * dx + dy * dy)
}
// Mutating method (for value types)
mutating func moveBy(dx: Double, dy: Double) {
// self = Point(x: x + dx, y: y + dy)
}
}
let p1 = Point(x: 3, y: 4)
print(p1.magnitude) // 5.0
print(p1.distance(to: Point(x: 0, y: 0))) // 5.0
// Struct with default values
struct User {
var name: String
var email: String
var age: Int = 0
var isActive: Bool = true
}
var alice = User(name: "Alice", email: "alice@test.com")
alice.age = 28 // Can modify properties of var structClasses
SWIFT
// Classes are reference types (shared)
class BankAccount {
let owner: String
private(set) var balance: Double
init(owner: String, balance: Double = 0) {
self.owner = owner
self.balance = balance
}
func deposit(_ amount: Double) {
balance += amount
}
func withdraw(_ amount: Double) -> Bool {
guard balance >= amount else { return false }
balance -= amount
return true
}
}
let account = BankAccount(owner: "Alice", balance: 1000)
account.deposit(500)
account.withdraw(200) // trueStruct vs Class
| Aspect | Struct | Class |
|---|---|---|
| Type | Value (copied) | Reference (shared) |
| Identity | No | Yes (===) |
| Inheritance | No | Yes |
| Mutating | mutating keyword |
Automatic |
| Deinitializer | No | deinit |
| Default | Prefer this | When needed |
Use struct for: data models, views, value types Use class for: shared state, delegates, inheritance, Objective-C interop
Closures
SWIFT
// Basic closure
let greet = { (name: String) -> String in
return "Hello, \(name)!"
}
greet("Alice")
// Trailing closure syntax
func perform(action: () -> Void) {
action()
}
perform { print("Done!") }
// Closure with parameters
numbers.map { $0 * 2 } // $0 is first parameter
numbers.filter { $0 > 5 }
numbers.reduce(0, +)
// Sorting with closures
let names = ["Charlie", "Alice", "Bob"]
let sorted = names.sorted { $0 < $1 } // ["Alice", "Bob", "Charlie"]
// Closure capture
func makeCounter() -> () -> Int {
var count = 0
return {
count += 1 // Captures count
return count
}
}
let counter = makeCounter()
counter() // 1
counter() // 2
counter() // 3Common Closures in Swift
SWIFT
// Sorting
let sorted = names.sorted(by: { (a, b) -> Bool in
return a < b
})
// Shorthand
let sorted2 = names.sorted { $0 < $1 }
// Filtering
let longNames = names.filter { $0.count > 3 }
// Mapping
let uppercased = names.map { $0.uppercased() }
// Reducing
let totalLength = names.reduce(0) { $0 + $1.count }
// Chaining
let result = names
.filter { $0.count > 3 }
.map { $0.uppercased() }
.sorted()
// completion handler pattern
func fetchData(from url: String, completion: @escaping (Result<Data, Error>) -> Void) {
// Async operation...
URLSession.shared.dataTask(with: URL(string: url)!) { data, response, error in
if let error = error {
completion(.failure(error))
} else if let data = data {
completion(.success(data))
}
}.resume()
}
// Usage
fetchData(from: "https://api.example.com") { result in
switch result {
case .success(let data):
print("Got \(data.count) bytes")
case .failure(let error):
print("Error: \(error)")
}
}💡 Tip: Default to structs. Only use classes when you need reference semantics (shared state), inheritance, or Objective-C compatibility.