Blockchain ク gainst to the list

This article uses the latest version of xcode 13 + macOS Big sur + iOS15

Subscribers to the Subscriber

Subscriber is also a protocol, which contains the Input data type, which corresponds to the Output type of Publisher and the amount of requested data.

Subscriber Agreement

Look at the Subscriber agreement first

public protocol Subscriber : CustomCombineIdentifierConvertible {
    associatedtype Input
    associatedtype Failure : Error
  
    func receive(subscription: Subscription)

    func receive(_ input: Self.Input) -> Subscribers.Demand
    func receive(completion: Subscribers.Completion<Self.Failure>)
}
Copy the code
  • CustomCombineIdentifierConvertible this is used to implement the agreementPublisherThe unique ID of the stream, which the system has extended to implement.
  • InputIs the input type, corresponding toPublishertheOutputtype
  • FailureIs an error type, corresponding toPublishertheFailuretype
  • func receive(subscription: Subscription)
    • Called when the Subscription is successful, passing the Subscription
    • whenSubscriberYou’re ready to start receiving data, and you can callsubscriptiontherequest(_:)Method requests data,request(_:)passSubscribers.DemandAs a parameter.
      • Subscribers.Demand.maxMaximum number of requests
      • Subscribers.Demand.noneRequest 0 elements
      • Subscribers.Demand.unlimitedInfinite number of requests
  • func receive(_ input: Self.Input) -> Subscribers.Demand
    • Called when the subscriber receives a message
    • inputIs to acceptInputType data
    • I need to return oneSubscribers.DemandIndicates that several more parameters are to be received
  • func receive(completion: Subscribers.Completion<Self.Failure>)
    • When the event ends the call

Next, define a Subscriber:

class TestSubscriber: Subscriber{
    func receive(subscription: Subscription) {
        print("Received Subscription")
        subscription.request(.max(1))}func receive(_ input: Int) -> Subscribers.Demand {
        print("Received Value", input)
        return .unlimited
    }
    
    func receive(completion: Subscribers.Completion<Never>) {
        print("Received completion")}}Copy the code

Simple run:

let sub = TestSubscriber()
(0 ..< 5).publisher.receive(subscriber: sub)
Copy the code

Running results:

Received Subscription
Received Value 0
Received Value 1
Received Value 2
Received Value 3
Received Value 4
Received completion
Copy the code

Func receive(subscription: subscription) ¶

 subscription.request(.none)
Copy the code

Run again:

Received Subscription
Copy the code

No data and no completion.

Modify the code below:

.
 func receive(subscription: Subscription) {
        print("Received Subscription")
        subscription.request(.max(2))}func receive(_ input: Int) -> Subscribers.Demand {
        print("Received Value", input)
        return .none
    }
.
Copy the code

Run again:

Received Subscription
Received Value 0
Received Value 1
Copy the code

Modify the code again

.
    func receive(_ input: Int) -> Subscribers.Demand {
        print("Received Value", input)
         return  input = = 0 ? .max(2) : .none
    }
.
Copy the code

Run again:

Received Subscription
Received Value 0
Received Value 1
Received Value 2
Received Value 3
Copy the code

By two modifications you can see that the number of accepted events is equal to the sum of the number of times subscription. Request plus the number returned by func receive(_ INPUT: Int) -> Subscribers.Demand.

sink

In Part I – Publisher many examples are used in the sink (receiveCompletion: receiveValue:), this method is by receiveCompletion and receiveValue closure to create subscriber to complete the subscription.

  • receiveCompletionCalled when Publisher returns is complete
  • receiveValueCalled when an event is received.

Sink (receiveCompletion: receiveValue:) a subscription request immediately successful an infinite number of data, the returned Cancellable object must hold, or Cancellable is released, the data flow will be canceled.

You can use the sink(receiveValue:) method if there is no need to complete processing or errors.

assign

Assgin will assign the received data to properties marked as publishers for redistribution.

Assgin can assign the received data to properties via keypath or inout. Here’s an example:

class Test{
    @Published var i: Int = 0
    @Published var ii: Int = 0
}

Copy the code

The variables I and II need to be decorated with the @Published attribute. The @Published attribute marks the attributes as Published, and $is used to get the attribute for publisher. The @Published modified property is commonly used in SwiftUI development and is a good way to connect a View to a ViewModel.

Test the above code:


class Test{
    @Published var i: Int = 0
    @Published var ii: Int = 0
}

let test = Test(a)Just(1).assign(to: \.i, on: test)
Just(3).assign(to: &test.$ii)
test.$i.sink(receiveValue: { print("i".$0)})
test.$ii.sink(receiveValue: { print("ii".$0)})

Copy the code

The output is as follows:

i 1
ii 3
Copy the code