You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/aboutthisbook.adoc
+6-4Lines changed: 6 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,9 +18,9 @@ I am working through how to make it available to the widest audience while also
18
18
Joe Heck has broad software engineering development and management experience crossing startups and large companies.
19
19
He works across all the layers of solutions, from architecture, development, validation, deployment, and operations.
20
20
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.
24
24
25
25
Joe works extensively with and in open source, contributing and collaborating with a wide variety of open source projects.
26
26
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/.
35
35
== Where to get this book
36
36
37
37
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.
Copy file name to clipboardExpand all lines: docs/coreconcepts.adoc
+27-18Lines changed: 27 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,6 +13,7 @@ It is also described with two associated types, one for Input and one for Failur
13
13
When you connect a subscriber to a publisher, both types must match: Output to Input, and Failure to Failure.
14
14
You can view this as a series of operations on two types in parallel.
15
15
16
+
//TODO(heckj) - convert to a diagram
16
17
[source]
17
18
----
18
19
Publisher source Subscriber
@@ -28,6 +29,7 @@ You can create chains of these together, for processing, reacting, and transform
28
29
29
30
I'm calling these composed sequences **pipelines**.
30
31
32
+
//TODO(heckj) - convert to a diagram
31
33
[source]
32
34
----
33
35
Publisher source Operator Subscriber
@@ -59,16 +61,20 @@ let _ = Publishers.somePublisher
59
61
----
60
62
61
63
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.
63
66
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.
67
70
71
+
//TODO(heckj) change to xref to internal reference for these operators
68
72
An example of this is map and tryMap.
69
73
https://developer.apple.com/documentation/combine/publishers/map[`map`] allows for any combination of Output and Failure type and passes them through.
70
74
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.
71
75
76
+
In the example of `map`, you define the output type being returned in the closure you're providing to the operator.
77
+
72
78
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>`.
73
79
74
80
[#source-with-callouts]
@@ -108,26 +114,28 @@ In some cases, such as the example above, the compiler is unable to infer the re
108
114
Xcode (11 beta 2) displays this as the error message: `Unable to infer complex closure return type; add explicit type to disambiguate`.
109
115
****
110
116
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>>.
113
121
114
122
// force a page break - ignored in HTML rendering
115
123
<<<
116
124
117
125
[#core-lifecycle]
118
126
== Lifecycle of Publishers and Subscribers
119
127
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.
121
129
This is how Combine supports the concept of back pressure.
122
130
123
131
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.
125
133
This request is what drives calling all the closures up the composed pipeline.
126
134
127
135
Because subscribers drive the closure execution, it also allows Combine to support cancellation.
128
136
Cancellation can be triggered by the subscriber.
129
137
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.
131
139
132
140
* When the subscriber is attached to a publisher, it starts with a call to `.subscribe(Subscriber)`.
133
141
* The publisher in turn acknowledges the subscription calling `receive(subscription)`.
@@ -147,6 +155,7 @@ The https://developer.apple.com/documentation/combine/publisher[publisher protoc
147
155
148
156
Combine provides a number of convenience publishers:
149
157
158
+
//TODO(heckj) - convert to xref to reference sections on these operators
@@ -162,10 +171,12 @@ Combine provides a number of convenience publishers:
162
171
| @Published
163
172
164
173
| @ObjectBinding
174
+
|
175
+
|
165
176
166
177
|===
167
178
168
-
Other Apple APIs provide publishers as well
179
+
A number of additional Apple APIs provide publishers as well.
169
180
170
181
// TODO(heckj): come back and map these to xref's to the reference section when created
171
182
@@ -352,7 +363,7 @@ Operators can also help with error handling and retry logic, buffering and prefe
352
363
[#core-subjects]
353
364
== Subjects
354
365
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.
356
367
This protocol requires subjects to have a `.send()` method to allow the developer to send specific values to a subscriber (or pipeline).
357
368
358
369
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:
364
375
365
376
The first is https://developer.apple.com/documentation/combine/currentvaluesubject[`CurrentValueSubject`].
366
377
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.
369
379
370
380
It is created and initialized with an initial value.
371
381
When a subscriber is connected to it and requests data, the initial value is sent.
372
382
Further calls to `.send()` afterwards will then send those values to any subscribers.
373
383
374
384
The second is https://developer.apple.com/documentation/combine/passthroughsubject[`PassthroughSubject`].
375
385
376
-
** Passthrough doesn't maintain any state - just passes through provided values
386
+
* Passthrough doesn't maintain any state - just passes through provided values.
377
387
378
388
When it is created, only the types are defined.
379
389
When a subscriber is connected and requests data, it will not receive any values until a `.send()` call is invoked.
380
390
Calls to `.send()` will then send values to any subscribers.
381
391
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.
383
393
384
394
Both CurrentValueSubject and PassthroughSubject are also useful for creating publishers from objects conforming to https://developer.apple.com/documentation/swiftui/bindableobject[`BindableObject`] within SwiftUI.
385
395
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.
387
397
388
398
[#core-subscribers]
389
399
== Subscribers
390
400
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.
392
402
393
403
There are two subscribers built-in to Combine: assign and sink.
394
404
@@ -515,6 +525,5 @@ You may see this in code as an operator, for example:
Copy file name to clipboardExpand all lines: docs/introduction.adoc
+19-11Lines changed: 19 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ In Apple's words, Combine is:
6
6
[quote]
7
7
a declarative Swift API for processing values over time.
8
8
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].
10
10
RxSwift itself is a port of http://reactivex.io[ReactiveX].
11
11
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.
12
12
@@ -28,25 +28,29 @@ In addition, functional reactive programming includes functions to split streams
28
28
29
29
There are many parts of the systems we program that can be viewed as asynchronous streams of information - events, objects, or pieces of data.
30
30
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.
32
33
33
34
You may want to create logic to watch more than one element that is changing.
34
35
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.
37
38
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.
39
41
40
42
== Combine specifics
41
43
42
44
Applying these concepts to a strongly typed language like swift is part of what Apple has created in Combine.
43
45
Combine embeds the concept of back-pressure, which allows the subscriber to control how much information it gets at once and needs to process.
44
46
In addition, it supports efficient operation with the notion of streams that are cancellable and driven primarily by the subscriber.
45
47
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.
47
51
SwiftUI is the obvious example that has the most attention, with both subscriber and publisher elements.
48
52
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.
50
54
51
55
Any asynchronous operation API _can_ be leveraged with Combine.
52
56
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.
59
63
60
64
== When to use Combine
61
65
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.
63
67
User interfaces fit very naturally into this pattern.
64
68
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:
66
73
67
74
* You can set up pipelines to enable the button for submission only when values entered into the fields are valid.
68
75
* 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
90
97
91
98
=== WWDC content
92
99
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].
94
102
95
103
A number of these introduce and go into some depth on Combine:
96
104
@@ -100,7 +108,7 @@ A number of these introduce and go into some depth on Combine:
100
108
* https://developer.apple.com/videos/play/wwdc2019/721/[Combine in Practice]
101
109
** https://devstreaming-cdn.apple.com/videos/wwdc/2019/721ga0kflgr4ypfx/721/721_combine_in_practice.pdf?dl=1[PDF of presentation notes]
102
110
103
-
A number of additional sessions mention Combine:
111
+
A number of additional WWDC19 sessions mention Combine:
104
112
105
113
* https://developer.apple.com/videos/play/wwdc2019/415/[Modern Swift API Design]
106
114
* https://developer.apple.com/videos/play/wwdc2019/226[Data Flow Through SwiftUI]
0 commit comments