paint-brush
Nhà xuất bản hữu ích trong Swift: Hướng dẫn cần thiếttừ tác giả@vadimchistiakov
1,359 lượt đọc
1,359 lượt đọc

Nhà xuất bản hữu ích trong Swift: Hướng dẫn cần thiết

từ tác giả Vadim Chistiakov11m2023/01/18
Read on Terminal Reader

dài quá đọc không nổi

Nhà xuất bản là loại tuân theo giao thức `Nhà xuất bản`. Nó chịu trách nhiệm cung cấp một luồng giá trị cho người đăng ký. Nhà xuất bản có thể phát ra một hoặc nhiều giá trị theo thời gian và nó cũng có thể hoàn thành hoặc không thành công. Khung Combine cung cấp một số nhà xuất bản tích hợp.
featured image - Nhà xuất bản hữu ích trong Swift: Hướng dẫn cần thiết
Vadim Chistiakov HackerNoon profile picture
0-item

Tổng quan

Trong khung Kết hợp, nhà xuất bản là loại tuân theo giao thức Publisher . Nó chịu trách nhiệm cung cấp một luồng giá trị cho người đăng ký. Giao thức Publisher xác định hai loại liên quan: OutputFailure , cho biết loại giá trị mà nhà xuất bản có thể phát ra và loại lỗi mà nhà xuất bản có thể đưa ra tương ứng.


Nhà xuất bản có thể phát ra một hoặc nhiều giá trị theo thời gian và nó cũng có thể hoàn thành hoặc không thành công. Khi một người đăng ký đăng ký với một nhà xuất bản, nhà xuất bản gọi phương thức receive(subscription:) của người đăng ký và chuyển cho nó một đối tượng Subscription mà người đăng ký có thể sử dụng để kiểm soát luồng giá trị. Người đăng ký cũng có thể gọi phương thức receive(_:) trên nhà xuất bản để nhận các giá trị mới.


Khung Kết hợp cung cấp một số nhà xuất bản tích hợp, chẳng hạn như Just , Fail , Empty , DeferredSequence , có thể được sử dụng để tạo nhiều loại nhà xuất bản khác nhau. Ngoài ra, bạn có thể tạo nhà xuất bản tùy chỉnh của riêng mình bằng cách tuân thủ giao thức Publisher và triển khai các phương pháp bắt buộc.


Các nhà xuất bản cũng có thể được kết hợp với nhau để tạo ra các quy trình phức tạp hơn. Khung Kết hợp cung cấp một số toán tử tích hợp có thể được sử dụng để sửa đổi và kết hợp các nhà xuất bản, chẳng hạn như map , filter , reduce , flatMap , zipmerge . Các toán tử này được cung cấp bởi phần mở rộng giao thức của Publisher và có thể được gọi trên bất kỳ nhà xuất bản nào.


Bây giờ tôi muốn cung cấp cho bạn một số nhà xuất bản hữu ích mà tôi sử dụng trong các dự án của mình.

Nhà xuất bản hẹn giờ lặp lại

Để triển khai một nhà xuất bản sử dụng bộ hẹn giờ lặp lại với khoảng thời gian tùy chỉnh trong Swift, bạn có thể sử dụng lớp Bộ Timer từ Foundation framework. Đây là một ví dụ về cách bạn có thể làm điều đó:


RepeatingTimeSubscription phù hợp với giao thức Subscription :


 private class RepeatingTimerSubscription<S: Subscriber>: Subscription where S.Input == Void { private let interval: TimeInterval private let queue: DispatchQueue private var subscriber: S? private var timer: Timer? init(interval: TimeInterval, queue: DispatchQueue, subscriber: S) { self.interval = interval self.queue = queue self.subscriber = subscriber } func request(_ demand: Subscribers.Demand) { timer?.invalidate() timer = Timer.scheduledTimer( withTimeInterval: interval, repeats: true ) { [weak self] _ in self?.queue.async { _ = self?.subscriber?.receive() } } } func cancel() { timer?.invalidate() timer = nil subscriber = nil } }


RepeatingTimePublisher tuân thủ giao thức của Publisher :


 import Foundation import Combine final class RepeatingTimerPublisher: Publisher { typealias Output = Void typealias Failure = Never private let interval: TimeInterval private let queue: DispatchQueue init(interval: TimeInterval, queue: DispatchQueue = .main) { self.interval = interval self.queue = queue } func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { let subscription = RepeatingTimerSubscription( interval: interval, queue: queue, subscriber: subscriber ) subscriber.receive(subscription: subscription) } }



Để sử dụng nhà xuất bản này, bạn có thể tạo một phiên bản của nó và đăng ký nó bằng cách sử dụng phương pháp sink của giao thức Publisher .


Ví dụ:

 private var cancellable: AnyCancellable? func subscribeOnTimer(interval: TimeInterval) { let publisher = RepeatingTimerPublisher(interval: interval) cancellable = publisher.sink { print("Timer fired!") } } //TEST THE METHOD subscribeOnTimer(interval: 5.0)


Thao tác này sẽ in "Hẹn giờ đã kích hoạt!" cứ sau 5 giây. Bạn có thể hủy đăng ký bằng cách gọi phương thức cancel trên đối tượng AnyCancellable được trả về bởi phương thức sink .


Ví dụ:


 deinit { cancellable?.cancel() }


Nhà xuất bản bỏ phiếu dài

Để triển khai tính năng bỏ phiếu dài bằng cách sử dụng khung Kết hợp trong Swift, bạn có thể tạo một nhà xuất bản đưa ra yêu cầu mạng ở một khoảng thời gian xác định và trả về phản hồi làm đầu ra. Đây là một ví dụ về cách bạn có thể làm điều đó:


Enum lỗi tùy chỉnh cho các trường hợp không thành công.

 enum CustomError: Error { case invalidResponse case invalidDecoding case error }


LongPollingSubscription phù hợp với giao thức Subscription :


 private class LongPollingSubscription<S: Subscriber, Output: Decodable>: Subscription where S.Input == Output, S.Failure == CustomError { private let url: URL private let interval: TimeInterval private let decoder: JSONDecoder private var subscriber: S? private var timer: Timer? private var task: URLSessionDataTask? init( url: URL, interval: TimeInterval, subscriber: S, decoder: JSONDecoder = JSONDecoder() ) { self.url = url self.interval = interval self.subscriber = subscriber self.decoder = decoder } func request(_ demand: Subscribers.Demand) { timer?.invalidate() timer = Timer.scheduledTimer( withTimeInterval: interval, repeats: true ) { [weak self] _ in self?.makeRequest() } makeRequest() } func cancel() { timer?.invalidate() timer = nil task?.cancel() task = nil subscriber = nil } private func makeRequest() { task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in guard let self else { return } if let error = error as? S.Failure { self.subscriber?.receive( completion: .failure(error) ) return } guard let data else { self.subscriber?.receive( completion: .failure(.invalidResponse) ) return } do { let output = try self.decoder.decode( Output.self, from: data ) _ = self.subscriber?.receive(output) } catch { self.subscriber?.receive( completion: .failure(.invalidDecoding) ) } } task?.resume() } }


LongPollingPublisher tuân thủ giao thức của Publisher :


 final class LongPollingPublisher<Output: Decodable>: Publisher { typealias Failure = CustomError private let url: URL private let interval: TimeInterval init(url: URL, interval: TimeInterval) { self.url = url self.interval = interval } func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { let subscription = LongPollingSubscription( url: url, interval: interval, subscriber: subscriber ) subscriber.receive(subscription: subscription) } }


<Output: Decodable> có nghĩa là bạn có thể sử dụng bất kỳ loại phản hồi chung nào phù hợp với Decodable thức Có thể giải mã.


Để thử nghiệm, bạn cần tạo một mô hình phù hợp với Decodable . Tôi sử dụng API công khai của https://pixabay.com/api .


Hãy để nó là cấu trúc PhotoResponse:


 struct PhotoResponse: Decodable { struct Photo: Decodable { let user: String let id: Int let largeImageURL: String } let hits: [Photo] let total: Int }


Để sử dụng nhà xuất bản này, bạn có thể tạo một phiên bản của nó và đăng ký nó bằng cách sử dụng phương pháp sink của giao thức Publisher . Ví dụ:


 private var cancellable: AnyCancellable? private func pollingTest() { let url = URL(string: "https://pixabay.com/api/?key={your_key}")! let publisher = LongPollingPublisher<PhotoResponse>( url: url, interval: 5.0 ) cancellable = publisher.sink(receiveCompletion: { completion in switch completion { case .finished: print("Completed") case .failure(let error): print("Error: \(error)") } }, receiveValue: { response in print("Received response: \(response)") }) } //TEST THE METHOD pollingTest()


Một điều nữa

Có một số nhà xuất bản tùy chỉnh hữu ích có thể được tạo bằng cách sử dụng khung Kết hợp trong Swift. Đây là vài ví dụ:

  1. NotificationCenterPublisher : Nhà xuất bản phát ra các giá trị khi một thông báo cụ thể được đăng lên NotificationCenter . Bạn có thể sử dụng nhà xuất bản này để phản ứng với các sự kiện dành riêng cho hệ thống hoặc ứng dụng, chẳng hạn như xoay thiết bị hoặc thay đổi trạng thái mạng.
  2. KeyboardPublisher : Nhà xuất bản phát ra các giá trị khi bàn phím được hiển thị hoặc ẩn. Bạn có thể sử dụng nhà xuất bản này để điều chỉnh bố cục của chế độ xem của mình khi bàn phím được hiển thị hoặc loại bỏ.
  3. CoreLocationPublisher : Nhà xuất bản đưa ra các giá trị khi vị trí của người dùng thay đổi. Nhà xuất bản này có thể được sử dụng để theo dõi vị trí của người dùng và thực hiện các hành động dựa trên vị trí của họ.
  4. UIControlEventPublisher : Nhà xuất bản phát ra giá trị khi một sự kiện cụ thể xảy ra trên UIControl chẳng hạn như UIButton hoặc UITextField. Điều này có thể được sử dụng để xử lý các tương tác của người dùng theo cách phản ứng.

Đây chỉ là một vài ví dụ về các loại nhà xuất bản tùy chỉnh có thể được tạo bằng cách sử dụng khung Kết hợp. Điều quan trọng là hiểu các yêu cầu của ứng dụng của bạn và sử dụng các khối xây dựng có sẵn do khung cung cấp để tạo các nhà xuất bản đáp ứng các yêu cầu đó.

Tóm lại là

Cuối cùng, điều quan trọng cần lưu ý là khung Kết hợp sử dụng mô hình lập trình phản ứng chức năng, đây là mô hình lập trình xử lý các luồng sự kiện theo thời gian. Các nhà xuất bản, cùng với người đăng ký và nhà khai thác, là các khối xây dựng cốt lõi của mô hình này và họ giúp dễ dàng tạo các ứng dụng phức tạp và đáp ứng.

L O A D I N G
. . . comments & more!

About Author

Vadim Chistiakov HackerNoon profile picture
Vadim Chistiakov@vadimchistiakov
iOS team lead, developer. 6 years experience of specializing in mobile development. Super nerd who loves Apple and code

chuyên mục

BÀI VIẾT NÀY CŨNG CÓ MẶT TẠI...