Closures trong Swift
1. Giới thiệu
Closures là anonymous functions có thể capture và lưu trữ references đến biến và hằng số.
2. Cú pháp cơ bản
// Cú pháp đầy đủ
let greet = { (name: String) -> String in
return "Hello, \(name)!"
}
print(greet("Alice")) // Hello, Alice!3. Cú pháp ngắn gọn
let numbers = [1, 2, 3, 4, 5]
// Đầy đủ
let doubled1 = numbers.map({ (n: Int) -> Int in return n * 2 })
// Inferring type
let doubled2 = numbers.map({ n in return n * 2 })
// Implicit return
let doubled3 = numbers.map({ n in n * 2 })
// Shorthand argument names
let doubled4 = numbers.map({ $0 * 2 })
// Trailing closure
let doubled5 = numbers.map { $0 * 2 }4. Trailing Closure
func performOperation(_ operation: () -> Void) {
operation()
}
// Trailing closure syntax
performOperation {
print("Hello!")
}
// Multiple trailing closures
func fetch(
onSuccess: (String) -> Void,
onError: (Error) -> Void
) {
onSuccess("Data")
}
fetch { data in
print("Got: \(data)")
} onError: { error in
print("Error: \(error)")
}5. Closures với Collections
let numbers = [3, 1, 4, 1, 5, 9, 2, 6]
// filter
let evens = numbers.filter { $0 % 2 == 0 }
print(evens) // [4, 2, 6]
// sorted
let sorted = numbers.sorted { $0 < $1 }
// reduce
let sum = numbers.reduce(0) { $0 + $1 }
print(sum) // 31
// compactMap
let strings = ["1", "two", "3"]
let ints = strings.compactMap { Int($0) }
print(ints) // [1, 3]6. Capturing Values
func makeCounter() -> () -> Int {
var count = 0
return {
count += 1
return count
}
}
let counter = makeCounter()
print(counter()) // 1
print(counter()) // 2
print(counter()) // 37. Capture List
class ViewController {
var name = "Main"
func doSomething() {
// Capture self weakly để tránh retain cycle
let closure = { [weak self] in
guard let self = self else { return }
print(self.name)
}
closure()
}
}8. @escaping Closures
class NetworkManager {
var completionHandler: ((String) -> Void)?
func fetch(completion: @escaping (String) -> Void) {
// Closure được lưu để gọi sau
completionHandler = completion
DispatchQueue.main.async {
completion("Data loaded")
}
}
}9. @autoclosure
func logIfNeeded(_ condition: Bool, message: @autoclosure () -> String) {
if condition {
print(message())
}
}
logIfNeeded(true, message: "Expensive string: \(computeValue())")
// Chỉ compute khi condition = true10. Ví dụ thực tế
struct User: Codable {
let name: String
let age: Int
}
func fetchUsers(completion: @escaping (Result<[User], Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data else { return }
do {
let users = try JSONDecoder().decode([User].self, from: data)
completion(.success(users))
} catch {
completion(.failure(error))
}
}.resume()
}📝 Tóm tắt
- Closure:
{ (params) -> ReturnType in body } $0, $1shorthand cho parameters- Trailing closure syntax cho code gọn
@escapingkhi closure được lưu/gọi sau[weak self]tránh retain cycles@autoclosurecho lazy evaluation
Last updated on
Swift