Giới thiệu
Combine sinh ra để làm gì, và phần nào đã bị thay thế
Combine là framework của Apple dành cho những giá trị đến theo thời gian: một phản hồi mạng, nội
dung một ô nhập liệu, một thông báo, một nhịp đồng hồ. Thay vì mỗi nguồn một callback, mọi nguồn đều
trở thành một Publisher, và các publisher ghép được với nhau.
let cancellable = NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification)
.compactMap { ($0.object as? UITextField)?.text }
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
.removeDuplicates()
.sink { query in search(query) }
Bốn toán tử thay cho một bộ đếm giờ debounce, một phép kiểm tra “có đổi không” và một delegate.
Cảnh báo
Phần lớn lý do Combine ra đời nay đã nằm sẵn trong ngôn ngữ. async/await xử lý việc chạy một
lần tốt hơn Future, còn AsyncSequence xử lý luồng dữ liệu với ít bộ máy hơn hẳn. Hãy dùng
Combine khi bạn thật sự cần vốn từ vựng toán tử của nó — trộn luồng, ghép giá trị mới nhất,
backpressure — chứ không phải theo quán tính.
Một lập trường thành thật về một framework đang đi xuống
Cuốn sách này sẽ không giả vờ rằng Combine là tương lai. Đã nhiều năm Apple không cập nhật gì đáng
kể cho nó, @Observable đã dẹp đi lý do mà phần lớn ứng dụng cần đến nó — ObservableObject và
@Published — và với công việc mới, concurrency có cấu trúc là lựa chọn mặc định tốt hơn trong hầu
hết tình huống.
Vậy sao lại viết cả một cuốn sách? Hai lý do, và cả hai đều thực dụng.
Nó nằm trong codebase bạn thừa kế. Combine đã đi vào rất nhiều code iOS sản xuất trong khoảng 2019 đến 2023, và đám code đó vẫn đang chạy. Đọc nó, gỡ lỗi nó và chuyển đổi nó từng phần đòi hỏi phải hiểu nó cho tử tế, còn “cứ viết lại bằng async/await đi” thì không phải một kế hoạch khi cái pipeline dài bốn trăm dòng và đang gánh cả hệ thống.
Vài bài toán vẫn còn vụng về nếu thiếu nó. Ghép giá trị mới nhất từ ba nguồn độc lập, debounce, throttle, thử lại với độ lùi tăng dần, chia sẻ một request đang bay cho nhiều subscriber — những việc này đều có lời giải bằng async/await, nhưng lời giải là viết tay, còn bản Combine thì mỗi việc đúng một toán tử.
Cách nói thành thật: Combine là một công cụ với tập hợp các công dụng tốt đang hẹp dần, và biết chính xác tập hợp ấy kết thúc ở đâu thì giá trị hơn cả sự nhiệt tình lẫn sự phủi tay.
Sách này nói về gì
Publisher và Subscriber là bản hợp đồng — các protocol, cái bắt tay bốn bước nằm dưới mọi luồng dữ liệu, các subject để bắc cầu với code mệnh lệnh, và demand, khái niệm mà phần lớn người dùng Combine không bao giờ học tới và là thứ giải thích những góc kỳ quặc của framework.
Toán tử là phần từ vựng, chia làm bốn chương nhóm theo việc chúng làm chứ không theo thứ tự bảng chữ cái: biến đổi, kết hợp, thời gian, và xử lý lỗi.
Scheduler và luồng thực thi nói về nơi công việc diễn ra và nơi giá trị được giao, hai câu hỏi khác nhau với hai câu trả lời khác nhau — và là nguồn gốc của phần lớn lỗi luồng trong Combine.
Hủy và vòng đời nói về AnyCancellable, những vòng giữ tham chiếu mà nó mời gọi, và vì sao một
luồng có thể dừng lặng lẽ mà không ghi lại gì.
Kiểm thử một pipeline nói về việc làm cho thời gian điều khiển được, để một bài test debounce không mất ba giây.
Combine và async/await là chương liên thông và cũng là chương chuyển đổi — .values, Future,
bắc cầu theo cả hai chiều, và cách quyết định phần nào của một pipeline có sẵn thì đáng chuyển đi.
Sách giả định gì
Swift, bao gồm generic và closure, cùng đủ kiến thức concurrency để biết một Task là gì. Sách không
giả định bạn từng dùng một framework reactive nào — không cần biết RxSwift, và ở đâu một cái tên
trong Combine khác với cái tên bên Rx mà quy ước sẽ gợi ra, sách sẽ nói rõ.