Closures
1. Giới thiệu
Phần tiêu đề “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
Phần tiêu đề “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
Phần tiêu đề “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 typelet doubled2 = numbers.map({ n in return n * 2 })
// Implicit returnlet doubled3 = numbers.map({ n in n * 2 })
// Shorthand argument nameslet doubled4 = numbers.map({ $0 * 2 })
// Trailing closurelet doubled5 = numbers.map { $0 * 2 }4. Trailing Closure
Phần tiêu đề “4. Trailing Closure”func performOperation(_ operation: () -> Void) { operation()}
// Trailing closure syntaxperformOperation { print("Hello!")}
// Multiple trailing closuresfunc 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
Phần tiêu đề “5. Closures với Collections”let numbers = [3, 1, 4, 1, 5, 9, 2, 6]
// filterlet evens = numbers.filter { $0 % 2 == 0 }print(evens) // [4, 2, 6]
// sortedlet sorted = numbers.sorted { $0 < $1 }
// reducelet sum = numbers.reduce(0) { $0 + $1 }print(sum) // 31
// compactMaplet strings = ["1", "two", "3"]let ints = strings.compactMap { Int($0) }print(ints) // [1, 3]6. Capturing Values
Phần tiêu đề “6. Capturing Values”func makeCounter() -> () -> Int { var count = 0 return { count += 1 return count }}
let counter = makeCounter()print(counter()) // 1print(counter()) // 2print(counter()) // 37. Capture List
Phần tiêu đề “7. 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
Phần tiêu đề “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
Phần tiêu đề “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ế
Phần tiêu đề “10. 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
Phần tiêu đề “📝 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