web-dev-qa-db-fra.com

Exemple de squelette pour Swift Combiner Publisher-Subscriber

Comme je porte du code Objective-C vers Swift, j'essaie de mieux comprendre le nouveau cadre Combine et comment je peux l'utiliser pour recréer un modèle de conception commun.

Dans ce cas, le modèle de conception est un objet unique (Manager, Service, etc.) avec lequel un certain nombre de "clients" peuvent s'enregistrer en tant que délégué pour recevoir des rappels. C'est un modèle de base 1: Beaucoup utilisant des délégués.

Combine semble idéal pour cela, mais l'exemple de code est un peu mince. Voici un exemple de travail, mais je ne suis pas sûr qu'il soit correct ou utilisé comme prévu. En particulier, je suis curieux de connaître les cycles de référence entre les objets.

class Service {

  let tweets = PassthroughSubject<String, Never>()

  func start() {
    // Simulate the need send to send updates.
    DispatchQueue.global(qos: .utility).async {
      while true {
        self.sendTweet()
        usleep(100000)
      }
    }
  }

  func sendTweet() {
    tweets.send("Message \(Date().timeIntervalSince1970)")
  }
}

class Client : Subscriber {
  typealias Input = String
  typealias Failure = Never

  let service:Service
  var subscription:Subscription?

  init(service:Service) {
    self.service = service

   // Is this a retain cycle?
   // Is this thread-safe? 
    self.service.tweets.subscribe(self) 
  }

  func receive(subscription: Subscription) {
    print("Received subscription: \(subscription)")

    self.subscription = subscription
    self.subscription?.request(.unlimited)
  }

  func receive(_ input: String) -> Subscribers.Demand {
    print("Received Tweet: \(input)")
    return .unlimited
  }

  func receive(completion: Subscribers.Completion<Never>) {
    print("Received completion")
  }
}

// Dependency injection is used a lot throughout the 
// application in a similar fashion to this:

let service = Service()
let client = Client(service:service)

// In the real world, the service is started when
// the application is launched and clients come-and-go.

service.start()

La sortie est:

Received subscription: PassthroughSubject
Received Tweet: Message 1560371698.300811
Received Tweet: Message 1560371698.4087949
Received Tweet: Message 1560371698.578027
...

Est-ce même à distance proche de la façon dont Combine devait être utilisé?

5
kennyc

L'abonné combiné personnalisé doit également se conformer au protocole annulable qui fournit une méthode pour transférer l'annulation à l'objet d'abonnement reçu de Publisher. De cette façon, vous n'avez pas à exposer la propriété d'abonnement. Selon le doc:

Si vous créez un abonné personnalisé, l'éditeur envoie un objet d'abonnement lorsque vous vous y abonnez pour la première fois. Stockez cet abonnement, puis appelez sa méthode cancel () lorsque vous souhaitez annuler la publication. Lorsque vous créez un abonné personnalisé, vous devez implémenter le protocole Annulable et demander à votre implémentation cancel () de transférer l'appel à l'abonnement stocké. https://developer.Apple.com/documentation/combine/receiving_and_handling_events_with_combine

1
dwiniarczuk