Skip to content

Conbini provides convenience Publishers, operators, and Subscribers to squeeze the most out of Apple’s Combine framework.

License

Notifications You must be signed in to change notification settings

GeekAndDad/Conbini

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Conbini icon

Conbini provides convenience Publishers, operators, and Subscribers to squeeze the most out of Apple's Combine framework.

Swift 5.1 platforms License

Operators

  • then ignores all values and executes the provided publisher once a successful completion is received. If a failed completion is emitted, it is forwarded downstream.
    let publisher = setConfigurationOnServer.then {
        subscribeToWebsocket.publisher
    }

Publishers

  • Complete never emits a value and just completes (whether successfully or with a failure). It offers similar functionality to Empty and Failure, but in a single type. Also, the completion only happens once a greater-than-zero demand is requested.

    let publisherA = Complete<Int,CustomError>(error: nil)
    let publisherB = Complete(error: CustomError())

    There are two more convenience initializers setting the publisher's Output and/or Failure to Never if the generic types are not explicitly stated.

  • Deferred... publishers accept a closure that is executed once a greater-than-zero demand is requested. They have several flavors:

    • DeferredValue emits a single value and then completes; however, the value is not provided/cached, but instead a closure which will generate the emitted value is executed per subscription received.

      let publisher = DeferredValue {
          return try someHeavyCalculations()
      }
    • DeferredResult offers the same functionality as DeferredValue, but the closure generates a Result instead.

      let publisher = DeferredResult {
        guard someExpression else { return .failure(CustomError()) }
        return .success(someValue)
      }
    • DeferredCompletion offers the same functionality as DeferredValue, but the closure only generates a completion event.

      let publisher = DeferredCompletion {
        try somethingThatMightFail()
      }
    • DeferredPassthrough is similar to wrapping a Passthrough subject on a Deferred closure, with the diferrence that the Passthrough given on the closure is already wired on the publisher chain and can start sending values right away. Also, the memory management is taken care of and every new subscriber receives a new subject (closure re-execution).

      let publisher = DeferredPassthrough { (subject) in
        subject.send(something)
        subject.send(completion: .finished)
      }

    There are several reason for these publishers to exist instead of using other Combine-provided closure such as Just, Future, or Deferred:

    • Future publishers execute their provided closure right away (upon initialization) and then cache the returned value. That value is then forwarded for any future subscription. Deferred... closures await for subscriptions and a greater-than-zero demand before executing. This also means, the closure will re-execute for any new subscription.
    • Deferred is the most similar in functionality, but it only accepts a publisher.
  • Then provides the functionality of the then operator.

Subscribers

The following operators are actually testing subscribers. They allow easier testing for publisher chains making the test wait till a specific expectation is fulfilled (or making the test fail in a negative case). Furthermore, if a timeout ellapses or a expectation is not fulfilled, the affected test line will be marked in red correctly in Xcode.

  • expectsCompletion subscribes to a publisher making the running test wait for a successful completion while ignoring all emitted values.

    publisherChain.expectsCompletion(timeout: 0.8, on: test)
  • expectsFailure subscribes to a publisher making the running test wait for a failed completion while ignoring all emitted values.

    publisherChain.expectsFailure(timeout: 0.8, on: test)
  • expectsOne subscribes to a publisher making the running test wait for a single value and a successful completion. If more than one values are emitted or the publisher fails, the subscription gets cancelled and the test fails.

    let emittedValue = publisherChain.expectsOne(timeout: 0.8, on: test)
  • expectsAll subscribes to a publisher making the running test wait for zero or more values and a successful completion.

    let emittedValues = publisherChain.expectsAll(timeout: 0.8, on: test)
  • expectAtLeast subscribes to a publisher making the running test wait for at least the provided amount of values. Once the provided amount of values is received, the publisher gets cancelled and the values are returned.

    let emittedValues = publisherChain.expectsAtLeast(values: 5, timeout: 0.8, on: test)

    This operator/subscriber accepts an optional closure to check every value received.

    let emittedValues = publisherChain.expectsAtLeast(values: 5, timeout: 0.8, on: test) { (value) in
      XCTAssert...
    }

References

The framework name references both the Combine framework and the helpful Japanese convenience stores 😄

About

Conbini provides convenience Publishers, operators, and Subscribers to squeeze the most out of Apple’s Combine framework.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 100.0%