Skip to content

Commit 6984e7e

Browse files
committed
doing an existing content edit pass while I wait for structural feedback
1 parent 0f05b45 commit 6984e7e

File tree

4 files changed

+52
-34
lines changed

4 files changed

+52
-34
lines changed

docs/aboutthisbook.adoc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ I am working through how to make it available to the widest audience while also
1818
Joe Heck has broad software engineering development and management experience crossing startups and large companies.
1919
He works across all the layers of solutions, from architecture, development, validation, deployment, and operations.
2020

21-
Joe has developed projects ranging from mobile and desktop application development to large cloud-based distributed systems.
22-
He has established development processes, CI and CD pipelines, and developed validation and operational automation for software solutions.
23-
Joe also builds teams and mentors people to learn, build, validate, deploy and run software services and infrastructure.
21+
Joe has developed projects ranging from mobile and desktop application development to cloud-based distributed systems.
22+
He has established teams, development processes, CI and CD pipelines, and developed validation and operational automation.
23+
Joe also builds and mentors people to learn, build, validate, deploy and run software services and infrastructure.
2424

2525
Joe works extensively with and in open source, contributing and collaborating with a wide variety of open source projects.
2626
He writes online across a variety of topics at https://rhonabwy.com/.
@@ -35,7 +35,9 @@ He writes online across a variety of topics at https://rhonabwy.com/.
3535
== Where to get this book
3636

3737
The contents of this book are available as https://heckj.github.io/swiftui-notes/[HTML], https://heckj.github.io/swiftui-notes/using-combine-book.pdf[PDF], and https://heckj.github.io/swiftui-notes/using-combine-book.epub[ePub].
38-
There is also an Xcode project (`SwiftUI-Notes.xcodeproj`) available from GitHub.
38+
39+
There is also an Xcode project (`SwiftUI-Notes.xcodeproj`) https://github.com/heckj/swiftui-notes[available on GitHub].
40+
The project includes tests, snippets, and trials used in creating this work.
3941

4042
=== Download the project
4143

docs/coreconcepts.adoc

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ It is also described with two associated types, one for Input and one for Failur
1313
When you connect a subscriber to a publisher, both types must match: Output to Input, and Failure to Failure.
1414
You can view this as a series of operations on two types in parallel.
1515

16+
//TODO(heckj) - convert to a diagram
1617
[source]
1718
----
1819
Publisher source Subscriber
@@ -28,6 +29,7 @@ You can create chains of these together, for processing, reacting, and transform
2829

2930
I'm calling these composed sequences **pipelines**.
3031

32+
//TODO(heckj) - convert to a diagram
3133
[source]
3234
----
3335
Publisher source Operator Subscriber
@@ -59,16 +61,20 @@ let _ = Publishers.somePublisher
5961
----
6062

6163
When you are viewing a pipeline, or creating one, you can think of it as a sequence of operations linked by the types.
62-
This pattern will come in handy when you start constructing your own pipelines, as some of operators will either require conformance of a type, or will change the Failure output type.
64+
This pattern will come in handy when you start constructing your own pipelines.
65+
With enforced types, there are a number of Combine functions that are created to help with these transformations.
6366

64-
Because the types are enforced, there are a number of Combine functions that are created to help with these transformations.
65-
Some operators are prefixed with `try` that indicate that they will return an <Error> type.
66-
In some cases, you may need to define the type being returned in the closure you're providing to the operator.
67+
Some operators will may require conformance of an input or failure type.
68+
Other operators may change either or both the failure and output types.
69+
For example, there are a number of operators that have a similar operator prexed with `try` indicating they return an <Error> failure type.
6770

71+
//TODO(heckj) change to xref to internal reference for these operators
6872
An example of this is map and tryMap.
6973
https://developer.apple.com/documentation/combine/publishers/map[`map`] allows for any combination of Output and Failure type and passes them through.
7074
https://developer.apple.com/documentation/combine/publishers/trymap['tryMap'] accepts any Input, Failure types, and allows any Output type, but will always output an `<Error>` failure type.
7175

76+
In the example of `map`, you define the output type being returned in the closure you're providing to the operator.
77+
7278
To illustrate changing types within a pipeline, here is a short snippet thsat starts with a publisher that generates `<Int>`, `<Never>` and end with a subscription taking `<String>`, `<Never>`.
7379

7480
[#source-with-callouts]
@@ -108,26 +114,28 @@ In some cases, such as the example above, the compiler is unable to infer the re
108114
Xcode (11 beta 2) displays this as the error message: `Unable to infer complex closure return type; add explicit type to disambiguate`.
109115
****
110116

111-
Combine supports error handling by creating two streams - one for the functional case and one for the error case, and combining them together.
112-
We will see that in more detail in the <<patterns.adoc#patterns,section on patterns>>.
117+
You can view Combine publishers, operators, and subscribers as having two parallel types that both need to be aligned - one for the functional case and one for the error case.
118+
Designing your pipeline is frequently choosing how to convert one or both of those types and the associated data with it.
119+
120+
Examples of this, and some common tasks, are detailed in the <<patterns.adoc#patterns,section on patterns>>.
113121

114122
// force a page break - ignored in HTML rendering
115123
<<<
116124

117125
[#core-lifecycle]
118126
== Lifecycle of Publishers and Subscribers
119127

120-
The interals of Combine are all driven by the subscriber.
128+
The data flow in Combine is driven by, and starts from, the subscriber.
121129
This is how Combine supports the concept of back pressure.
122130

123131
Internally, Combine supports this with the enumeration https://developer.apple.com/documentation/combine/subscribers/demand[Demand].
124-
When a subscriber is communicating with a publisher, it requests based on demand.
132+
When a subscriber is communicating with a publisher, it requests data based on demand.
125133
This request is what drives calling all the closures up the composed pipeline.
126134

127135
Because subscribers drive the closure execution, it also allows Combine to support cancellation.
128136
Cancellation can be triggered by the subscriber.
129137

130-
This is all built on subscribers and publishers communicating in a well defined sequence, or lifecycle.
138+
This is all enabled by subscribers and publishers communicating in a well defined sequence, or lifecycle.
131139

132140
* When the subscriber is attached to a publisher, it starts with a call to `.subscribe(Subscriber)`.
133141
* The publisher in turn acknowledges the subscription calling `receive(subscription)`.
@@ -147,6 +155,7 @@ The https://developer.apple.com/documentation/combine/publisher[publisher protoc
147155

148156
Combine provides a number of convenience publishers:
149157

158+
//TODO(heckj) - convert to xref to reference sections on these operators
150159
[cols="3*^"]
151160
|===
152161
| https://developer.apple.com/documentation/combine/publishers/empty[`Publishers.Empty`]
@@ -162,10 +171,12 @@ Combine provides a number of convenience publishers:
162171
| @Published
163172

164173
| @ObjectBinding
174+
|
175+
|
165176

166177
|===
167178

168-
Other Apple APIs provide publishers as well
179+
A number of additional Apple APIs provide publishers as well.
169180

170181
// TODO(heckj): come back and map these to xref's to the reference section when created
171182

@@ -352,7 +363,7 @@ Operators can also help with error handling and retry logic, buffering and prefe
352363
[#core-subjects]
353364
== Subjects
354365

355-
Subjects are a special case of publisher that also adhere to https://developer.apple.com/documentation/combine/subject[`subject`] protocol.
366+
Subjects are a special case of publisher that also adhere to the https://developer.apple.com/documentation/combine/subject[`subject`] protocol.
356367
This protocol requires subjects to have a `.send()` method to allow the developer to send specific values to a subscriber (or pipeline).
357368

358369
Subjects can be used to "inject" values into a stream, by calling the subject's `.send()` method.
@@ -364,31 +375,30 @@ There are two built-in subjects with Combine:
364375

365376
The first is https://developer.apple.com/documentation/combine/currentvaluesubject[`CurrentValueSubject`].
366377

367-
** CurrentValue remembers the current value so that when you attach a subscriber you can see the current value
368-
378+
* CurrentValue remembers the current value so that when a subscriber is attached, it immediately receives the current value.
369379
370380
It is created and initialized with an initial value.
371381
When a subscriber is connected to it and requests data, the initial value is sent.
372382
Further calls to `.send()` afterwards will then send those values to any subscribers.
373383

374384
The second is https://developer.apple.com/documentation/combine/passthroughsubject[`PassthroughSubject`].
375385

376-
** Passthrough doesn't maintain any state - just passes through provided values
386+
* Passthrough doesn't maintain any state - just passes through provided values.
377387
378388
When it is created, only the types are defined.
379389
When a subscriber is connected and requests data, it will not receive any values until a `.send()` call is invoked.
380390
Calls to `.send()` will then send values to any subscribers.
381391

382-
PassthroughSubject is extremely useful when writing tests for pipelines, as the sending of any requested data (or a failure) is under test control using the `.send()` function.
392+
PassthroughSubject is extremely useful when writing tests for pipelines, as sending of any requested data (or a failure) is under the test writer's control using the `.send()` function.
383393

384394
Both CurrentValueSubject and PassthroughSubject are also useful for creating publishers from objects conforming to https://developer.apple.com/documentation/swiftui/bindableobject[`BindableObject`] within SwiftUI.
385395

386-
Subjects can also be useful for fanning out values to multiple subscribers.
396+
Subjects is also useful for fanning out values to multiple subscribers.
387397

388398
[#core-subscribers]
389399
== Subscribers
390400

391-
While https://developer.apple.com/documentation/combine/subscriber[`subscriber`] is the protocol used to receive data throughout a pipeline, the Subscriber typically refers to the end of a pipeline.
401+
While https://developer.apple.com/documentation/combine/subscriber[`subscriber`] is the protocol used to receive data throughout a pipeline, _the Subscriber_ typically refers to the end of a pipeline.
392402

393403
There are two subscribers built-in to Combine: assign and sink.
394404

@@ -515,6 +525,5 @@ You may see this in code as an operator, for example:
515525
.receive(on: RunLoop.main)
516526
----
517527

518-
519528
// force a page break - ignored in HTML rendering
520529
<<<

docs/introduction.adoc

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ In Apple's words, Combine is:
66
[quote]
77
a declarative Swift API for processing values over time.
88

9-
Combine is Apple's take on a functional reactive library, akin to https://github.com/ReactiveX/RxSwift[RxSwift].
9+
Combine is Apple's take on a functional reactive programming library, akin to https://github.com/ReactiveX/RxSwift[RxSwift].
1010
RxSwift itself is a port of http://reactivex.io[ReactiveX].
1111
Apple's framework uses many of the same functional reactive concepts that can be found in other languages and libraries, applying the strongly-typed nature of Swift to their solution.
1212

@@ -28,25 +28,29 @@ In addition, functional reactive programming includes functions to split streams
2828

2929
There are many parts of the systems we program that can be viewed as asynchronous streams of information - events, objects, or pieces of data.
3030
Programming practices defined the Observer pattern for watching a single object, getting notified of changes and updates.
31-
As this happens over time, you can view the updates as a stream of objects.
31+
If you view this over time, these updates make up a stream of objects.
32+
Functional reactive programming, or Combine in this case, allows you to create code that describes what happens when getting data in a stream.
3233

3334
You may want to create logic to watch more than one element that is changing.
3435
You may also want to include logic that does additional asynchronous operations, some of which may fail.
35-
You may also want to change the content of the streams based on timing.
36-
Handling the flow of all these event streams, the timing of all the various pieces, errors when they happen, and coordinating how a system responds to all those events is at the heart of this kind of programming.
36+
You may also want to change the content of the streams based on timing, or change the timing of the content.
37+
Handling the flow of these event streams, the timing, errors when they happen, and coordinating how a system responds to all those events is at the heart of this kind of programming.
3738

38-
This solution is particularly effective when programming user interfaces, or for creating pipelines that process and transform data from external sources, or rely on asynchronous APIs.
39+
A solution based on functional reactive programming is particularly effective when programming user interfaces.
40+
Or more generally for creating pipelines that process data from external sources or rely on asynchronous APIs.
3941

4042
== Combine specifics
4143

4244
Applying these concepts to a strongly typed language like swift is part of what Apple has created in Combine.
4345
Combine embeds the concept of back-pressure, which allows the subscriber to control how much information it gets at once and needs to process.
4446
In addition, it supports efficient operation with the notion of streams that are cancellable and driven primarily by the subscriber.
4547

46-
Combine was also set up to be composed, and Combine is explicitly supported by a couple of Apple's other frameworks.
48+
Combine is set up to be composed, and includes affordances to integrate existing code to incrementally support adoption.
49+
50+
Combine is supported by a couple of Apple's other frameworks.
4751
SwiftUI is the obvious example that has the most attention, with both subscriber and publisher elements.
4852
RealityKit also has publishers that you can use to react to events.
49-
NotificationCenter, URLSession, and Timer in the Foundation also now include publishers.
53+
And Foundation has a number of Combine specific additions including NotificationCenter, URLSession, and Timer as publishers.
5054

5155
Any asynchronous operation API _can_ be leveraged with Combine.
5256
For example, you could use some of the APIs in the Vision framework, composing data flowing to it, and from it, by leveraging Combine.
@@ -59,10 +63,13 @@ Pipeline is not a term that Apple is (yet?) using in its documentation.
5963

6064
== When to use Combine
6165

62-
Combine fits most naturally when you want to set up a system that is "immediately" reactive to a variety of inputs.
66+
Combine fits most naturally when you want to set up a something that is "immediately" reactive to a variety of inputs.
6367
User interfaces fit very naturally into this pattern.
6468

65-
The classic examples revolve around the user experience with form validation, where the inputs are text fields and a button for submitting.
69+
The classic examples in functional reactive programming and user interfaces frequently show form validation, where user events such as changing text fields, taps, or mouse-clicks on UI elements make up the data being streamed.
70+
Combine takes this quite a bit further, enabling watching of properties, binding to objects, sending and receiving higher level events from UI controls, and supporting integration with almost all of Apple's existing API ecosystem.
71+
72+
Some things you can do with Combine include:
6673

6774
* You can set up pipelines to enable the button for submission only when values entered into the fields are valid.
6875
* A pipeline can also do asynchronous actions (such as checking with a network service) and using the values returned to choose how and what to update within a view.
@@ -90,7 +97,8 @@ Apple's developer documentation is hosted at https://developer.apple.com/documen
9097

9198
=== WWDC content
9299

93-
Apple provides video, slides, and some sample code in sessions from https://developer.apple.com/videos/play/wwdc2019[WWDC 2019]
100+
Apple provides video, slides, and some sample code in sessions it's developer conferences.
101+
Details on Combine are primarily from https://developer.apple.com/videos/play/wwdc2019[WWDC 2019].
94102

95103
A number of these introduce and go into some depth on Combine:
96104

@@ -100,7 +108,7 @@ A number of these introduce and go into some depth on Combine:
100108
* https://developer.apple.com/videos/play/wwdc2019/721/[Combine in Practice]
101109
** https://devstreaming-cdn.apple.com/videos/wwdc/2019/721ga0kflgr4ypfx/721/721_combine_in_practice.pdf?dl=1[PDF of presentation notes]
102110

103-
A number of additional sessions mention Combine:
111+
A number of additional WWDC19 sessions mention Combine:
104112

105113
* https://developer.apple.com/videos/play/wwdc2019/415/[Modern Swift API Design]
106114
* https://developer.apple.com/videos/play/wwdc2019/226[Data Flow Through SwiftUI]

docs/using-combine-book.adoc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ v0.1, 2019-06-23
2323
ifndef::ebook-format[:leveloffset: 1]
2424

2525
include::aboutthisbook.adoc[]
26-
2726
include::introduction.adoc[]
2827
include::coreconcepts.adoc[]
2928
include::patterns.adoc[]

0 commit comments

Comments
 (0)