100% found this document useful (1 vote)
96 views

Full Download Combine Asynchronous Programming With Swift Third Edition Scott Gardner PDF

Third

Uploaded by

gjobeepin
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
96 views

Full Download Combine Asynchronous Programming With Swift Third Edition Scott Gardner PDF

Third

Uploaded by

gjobeepin
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 79

Full download ebooks at ebookmeta.

com

Combine Asynchronous Programming with Swift Third


Edition Scott Gardner

https://ebookmeta.com/product/combine-asynchronous-
programming-with-swift-third-edition-scott-gardner/

OR CLICK BUTTON

DOWLOAD NOW

Download more ebook from https://ebookmeta.com


More products digital (pdf, epub, mobi) instant
download maybe you interests ...

Combine Asynchronous Programming with Swift 2nd Edition


Scott Gardner

https://ebookmeta.com/product/combine-asynchronous-programming-
with-swift-2nd-edition-scott-gardner/

Asynchronous Programming with SwiftUI and Combine Peter


Friese

https://ebookmeta.com/product/asynchronous-programming-with-
swiftui-and-combine-peter-friese/

Transitioning to Swift Scott Gardner

https://ebookmeta.com/product/transitioning-to-swift-scott-
gardner/

Deep Learning with Swift for TensorFlow Differentiable


Programming with Swift 1st Edition Rahul Bhalley

https://ebookmeta.com/product/deep-learning-with-swift-for-
tensorflow-differentiable-programming-with-swift-1st-edition-
rahul-bhalley/
RxSwift Reactive Programming with Swift Second Edition
Raywenderlich.Com Team

https://ebookmeta.com/product/rxswift-reactive-programming-with-
swift-second-edition-raywenderlich-com-team/

iOS 15 Programming Fundamentals with Swift: Swift,


Xcode, and Cocoa Basics 1st Edition Matt Neuburg

https://ebookmeta.com/product/ios-15-programming-fundamentals-
with-swift-swift-xcode-and-cocoa-basics-1st-edition-matt-neuburg/

Head First Swift. A Learner’s Guide to Programming with


Swift 1st Edition Paris Buttfield-Addison

https://ebookmeta.com/product/head-first-swift-a-learners-guide-
to-programming-with-swift-1st-edition-paris-buttfield-addison/

The Swift Programming Language Swift 5 7 Apple Inc.

https://ebookmeta.com/product/the-swift-programming-language-
swift-5-7-apple-inc/

Head First Swift A Learner s Guide to Programming with


Swift 1st Edition Paris Buttfield Addison Jonathan
Manning

https://ebookmeta.com/product/head-first-swift-a-learner-s-guide-
to-programming-with-swift-1st-edition-paris-buttfield-addison-
jonathan-manning/
Combine: Asynchronous Programming with
Combine:
Swift Asynchronous Programming with Swift

Combine: Asynchronous Programming with


Swift
By Shai Mishali, Florent Pillet, Marin Todorov & Scott Gardner

Copyright ©2021 Razeware LLC.

Notice of Rights
All rights reserved. No part of this book or corresponding materials (such as text,
images, or source code) may be reproduced or distributed by any means without
prior written permission of the copyright owner.

Notice of Liability
This book and all corresponding materials (such as source code) are provided on an
“as is” basis, without warranty of any kind, express of implied, including but not
limited to the warranties of merchantability, fitness for a particular purpose, and
noninfringement. In no event shall the authors or copyright holders be liable for any
claim, damages or other liability, whether in action of contract, tort or otherwise,
arising from, out of or in connection with the software or the use of other dealing in
the software.

Trademarks
All trademarks and registered trademarks appearing in this book are the property of
their own respective owners.

raywenderlich.com 2
Combine: Asynchronous Programming with Swift

Table of Contents: Overview


Book License ............................................................................................. 12
Before You Begin ................................................................ 13
What You Need ........................................................................................ 14
Book Source Code & Forums ............................................................. 15
Acknowledgments .................................................................................. 18
Section I: Introduction to Combine .............................. 19
Chapter 1: Hello, Combine! .................................................... 20
Chapter 2: Publishers & Subscribers .................................. 37
Section II: Operators ......................................................... 72
Chapter 3: Transforming Operators ................................... 73
Chapter 4: Filtering Operators ............................................. 92
Chapter 5: Combining Operators ...................................... 114
Chapter 6: Time Manipulation Operators ..................... 140
Chapter 7: Sequence Operators ........................................ 168
Chapter 8: In Practice: Project "Collage Neue" ........... 190
Section III: Combine in Action ..................................... 210
Chapter 9: Networking .......................................................... 211
Chapter 10: Debugging ......................................................... 217
Chapter 11: Timers ................................................................. 223
Chapter 12: Key-Value Observing .................................... 229
Chapter 13: Resource Management ................................ 236

raywenderlich.com 3
Combine: Asynchronous Programming with Swift

Chapter 14: In Practice: Project "News" ........................ 245


Section IV: Advanced Combine ................................... 263
Chapter 15: In Practice: Combine & SwiftUI ................ 264
Chapter 16: Error Handling ................................................. 290
Chapter 17: Schedulers ......................................................... 320
Chapter 18: Custom Publishers & Handling
Backpressure ............................................................................. 344
Chapter 19: Testing ................................................................. 382
Section V: Building a Complete App .......................... 404
Chapter 20: In Practice: Building a Complete App ..... 405
Conclusion .............................................................................................. 432

raywenderlich.com 4
Combine: Asynchronous Programming with Swift

Table of Contents: Extended


Book License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Before You Begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
What You Need . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Book Source Code & Forums . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
About the Authors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Section I: Introduction to Combine . . . . . . . . . . . . . . . . 19
Chapter 1: Hello, Combine! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Asynchronous programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Swift’s Modern Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Foundation of Combine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Combine basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
What’s the benefit of Combine code over “standard” code? . . . . . . . . . . 31
App architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Book projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Where to go from here?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Chapter 2: Publishers & Subscribers. . . . . . . . . . . . . . . . . . . . . . . . . 37
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Hello Publisher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Hello Subscriber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Hello Cancellable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Understanding what’s going on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Creating a custom subscriber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Hello Future . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Hello Subject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

raywenderlich.com 5
Combine: Asynchronous Programming with Swift

Dynamically adjusting demand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62


Type erasure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Bridging Combine publishers to async/await . . . . . . . . . . . . . . . . . . . . . . . . . 65
Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Where to go from here?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

Section II: Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72


Chapter 3: Transforming Operators . . . . . . . . . . . . . . . . . . . . . . . . . 73
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Collecting values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Mapping values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Flattening publishers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Replacing upstream output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Incrementally transforming output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Where to go from here?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Chapter 4: Filtering Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Filtering basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Compacting and ignoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Finding values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Dropping values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Limiting values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Chapter 5: Combining Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Prepending . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

raywenderlich.com 6
Combine: Asynchronous Programming with Swift

Appending . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Advanced combining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Chapter 6: Time Manipulation Operators . . . . . . . . . . . . . . . . . . 140
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Shifting time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Collecting values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Collecting values (part 2) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Holding off on events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Timing out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Measuring time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Chapter 7: Sequence Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Finding values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Querying the publisher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Chapter 8: In Practice: Project "Collage Neue" . . . . . . . . . . . . . 190
Getting started with “Collage Neue” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Presenting views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Wrapping a callback function as a future . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Sharing subscriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Operators in practice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209

raywenderlich.com 7
Combine: Asynchronous Programming with Swift

Section III: Combine in Action . . . . . . . . . . . . . . . . . . . . 210


Chapter 9: Networking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
URLSession extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Codable support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Publishing network data to multiple subscribers . . . . . . . . . . . . . . . . . . . 214
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
Chapter 10: Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Printing events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
Acting on events — performing side effects . . . . . . . . . . . . . . . . . . . . . . . . . 220
Using the debugger as a last resort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Chapter 11: Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Using RunLoop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
Using the Timer class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
Using DispatchQueue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Chapter 12: Key-Value Observing . . . . . . . . . . . . . . . . . . . . . . . . . . 229
Introducing publisher(for:options:) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
Preparing and subscribing to your own KVO-compliant properties 230
ObservableObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
Chapter 13: Resource Management . . . . . . . . . . . . . . . . . . . . . . . 236
The share() operator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
The multicast(_:) operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Future . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

raywenderlich.com 8
Combine: Asynchronous Programming with Swift

Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244


Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Chapter 14: In Practice: Project "News" . . . . . . . . . . . . . . . . . . . 245
Getting started with the Hacker News API . . . . . . . . . . . . . . . . . . . . . . . . . 246
Getting a single story . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
Multiple stories via merging publishers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
Getting the latest stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
Challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262

Section IV: Advanced Combine . . . . . . . . . . . . . . . . . . . 263


Chapter 15: In Practice: Combine & SwiftUI . . . . . . . . . . . . . . . 264
Hello, SwiftUI! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
Getting started with “News” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
A first taste of managing view state . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Fetching the latest stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Using ObservableObject for model types . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
Displaying errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Subscribing to an external publisher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
Initializing the app’s settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
Editing the keywords list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
Chapter 16: Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Never . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Dealing with failure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319

raywenderlich.com 9
Combine: Asynchronous Programming with Swift

Chapter 17: Schedulers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320


An introduction to schedulers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
Operators for scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
Scheduler implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
Challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
Chapter 18: Custom Publishers & Handling Backpressure 344
Creating your own publishers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Publishers as extension methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
The subscription mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Publishers emitting values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
Publishers transforming values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
Handling backpressure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
Chapter 19: Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
Testing Combine operators. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
Testing production code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

Section V: Building a Complete App . . . . . . . . . . . . . . 404


Chapter 20: In Practice: Building a Complete App . . . . . . . . . 405
Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
Setting goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
Implementing JokesViewModel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
Wiring JokesViewModel up to the UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
Implementing Core Data with Combine . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420

raywenderlich.com 10
Combine: Asynchronous Programming with Swift

Challenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
Key points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
Where to go from here? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432

raywenderlich.com 11
L Book License

By purchasing Combine: Asynchronous Programming with Swift, you have the


following license:

• You are allowed to use and/or modify the source code in Combine: Asynchronous
Programming with Swift in as many apps as you want, with no attribution required.

• You are allowed to use and/or modify all art, images and designs that are included
in Combine: Asynchronous Programming with Swift in as many apps as you want, but
must include this attribution line somewhere inside your app: “Artwork/images/
designs: from Combine: Asynchronous Programming with Swift, available at
www.raywenderlich.com”.

• The source code included in Combine: Asynchronous Programming with Swift is for
your personal use only. You are NOT allowed to distribute or sell the source code
in Combine: Asynchronous Programming with Swift without prior authorization.

• This book is for your personal use only. You are NOT allowed to sell this book
without prior authorization, or distribute it to friends, coworkers or students; they
would need to purchase their own copies.

All materials provided with this book are provided on an “as is” basis, without
warranty of any kind, express or implied, including but not limited to the warranties
of merchantability, fitness for a particular purpose and noninfringement. In no event
shall the authors or copyright holders be liable for any claim, damages or other
liability, whether in an action or contract, tort or otherwise, arising from, out of or in
connection with the software or the use or other dealings in the software.

All trademarks and registered trademarks appearing in this guide are the properties
of their respective owners.

raywenderlich.com 12
Before You Begin

This section tells you a few things you need to know before you get started, such as
what you’ll need for hardware and software, where to find the project files for this
book, and more.

raywenderlich.com 13
i What You Need

To follow along with this book, you’ll need the following:

• A Mac running macOS Big Sur (11.0) or later. Catalina and earlier versions might
work, but they’re untested for this edition.

• Xcode 13 or later. Xcode is the main development tool for iOS. You’ll need Xcode
13 or later for the tasks in this book. Since Combine was introduced with the iOS
13 SDK, Xcode 12 should work as well - but the code in this book was tested
against Xcode 13. You can download the latest version of Xcode from Apple’s
developer site here: apple.co/2asi58y

• An intermediate level knowledge of Swift. This book teaches you how to write
declarative and reactive iOS applications using Apple’s Combine framework.
Combine uses a multitude of advanced Swift features such as generics, so you
should have at least an intermediate-level knowledge of Swift.

If you want to try things out on a physical iOS device, you’ll need a developer
account with Apple, which you can obtain for free. However, all the sample projects
in this book will work just fine in the iOS Simulator bundled with Xcode, so a paid
developer account is completely optional.

raywenderlich.com 14
ii Book Source Code &
Forums

Where to download the materials for this book


The materials for this book can be cloned or downloaded from the GitHub book
materials repository:

• https://github.com/raywenderlich/comb-materials/tree/editions/3.0

Forums
We’ve also set up an official forum for the book at https://
forums.raywenderlich.com/c/books/combine-asynchronous-programming-with-
swift. This is a great place to ask questions about the book or to submit any errors
you may find.

raywenderlich.com 15
“For my wife Elia and Baby Ethan—my love, inspiration, and
rock ❤ . To my family and friends for their support: Dad,
Mom, Ziv, Adam, and everyone else, you’re the best!”

— Shai Mishali

“To Fabienne and Alexandra ❤ .”

— Florent Pillet

“To my father. To my mom. To Mirjam and our beautiful


daughter.”

— Marin Todorov

raywenderlich.com 16
Combine: Asynchronous Programming with Swift About the Team

About the Authors


Shai Mishali is an author and the final pass editor on this book.
He’s an experienced, award-winning iOS specialist; as well as an
international speaker, and a highly active open-source contributor
and maintainer on several high-profile projects - namely, the
RxSwift Community and RxSwift projects, but also releases many
open-source endeavors around Combine such as CombineCocoa,
RxCombine and more. As an avid enthusiast of hackathons, Shai
took 1st place at BattleHack Tel-Aviv 2014, BattleHack World Finals
San Jose 2014, and Ford’s Developer Challenge Tel-Aviv 2015. You
can find him on GitHub (https://github.com/freak4pc) and Twitter
as @freak4pc (https://twitter.com/freak4pc).

Florent Pillet is an author of this book. He has been developing


for mobile platforms since the last century and moved to iOS on
day 1. He adopted reactive programming before Swift was
announced, using it in production since 2015. A freelance
developer, Florent also uses reactive programming on the server
side as well as on Android and likes working on tools for
developers like the popular NSLogger when he’s not contracting,
training or reviewing code for clients worldwide. Say hello to
Florent on Twitter (https://twitter.com/fpillet) and GitHub (https://
github.com/fpillet) at @fpillet.

Marin Todorov is an author of this book. Marin is one of the


founding members of the raywenderlich.com team and has worked
on eight of the team’s books. He’s an independent contractor and
has worked for clients like Roche, Realm, and others. Besides
crafting code, Marin also enjoys blogging, teaching and speaking at
conferences. He happily open-sources code. You can find out more
about Marin at www.underplot.com.

raywenderlich.com 17
v Acknowledgments

We would like to thank Scott Gardner for his work as an author on the previous
editions of this book.

raywenderlich.com 18
Section I: Introduction to
Combine

In this part of the book, you’re going to ramp up over the basics of Combine and
learn about some of the building blocks it comprises. You’ll learn what Combine aims
to solve and what are some of the abstractions it provides to help you solve them:
Publisher, Subscriber, Subscription, Subject and much more.

raywenderlich.com 19
1 Chapter 1: Hello,
Combine!
By Marin Todorov

This book aims to introduce you to the Combine framework and to writing
declarative, reactive apps with Swift for Apple platforms.

In Apple’s own words: “The Combine framework provides a declarative approach for
how your app processes events. Rather than potentially implementing multiple delegate
callbacks or completion handler closures, you can create a single processing chain for a
given event source. Each part of the chain is a Combine operator that performs a distinct
action on the elements received from the previous step.”

Although very accurate and to the point, this delightful definition might sound a
little too abstract at first. That’s why, before delving into coding exercises and
working on projects in the following chapters, you’ll take a little time to learn a bit
about the problems Combine solves and the tools it uses to do so.

Once you’ve built up the relevant vocabulary and some understanding of the
framework in general, you’ll move on to covering the basics while coding.

Gradually, as you progress in the book, you’ll learn about more advanced topics and
eventually work through several projects.

When you’ve covered everything else you will, in the last chapter, work on a
complete app built with Combine.

raywenderlich.com 20
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Asynchronous programming
In a simple, single-threaded language, a program executes sequentially line-by-line.
For example, in pseudocode:

begin
var name = "Tom"
print(name)
name += " Harding"
print(name)
end

Synchronous code is easy to understand and makes it especially easy to argue about
the state of your data. With a single thread of execution, you can always be sure what
the current state of your data is. In the example above, you know that the first print
will always print “Tom” and the second will always print “Tom Harding”.

Now, imagine you wrote the program in a multi-threaded language that is running
an asynchronous event-driven UI framework, like an iOS app running on Swift and
UIKit.

Consider what could potentially happen:

--- Thread 1 ---


begin
var name = "Tom"
print(name)

--- Thread 2 ---


name = "Billy Bob"

--- Thread 1 ---


name += " Harding"
print(name)
end

Here, the code sets name‘s value to "Tom" and then adds "Harding" to it, just like
before. But because another thread could execute at the same time, it’s possible that
some other part of your program could run between the two mutations of name and
set it to another value like "Billy Bob".

When the code is running concurrently on different cores, it’s difficult to say which
part of the code is going to modify the shared state first.

raywenderlich.com 21
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

The code running on “Thread 2” in the example above might be:

• executing at exactly the same time on a different CPU core as your original code.

• executing just before name += " Harding", so instead of the original value "Tom",
it gets "Billy Bob" instead.

What exactly happens when you run this code depends on the system load, and you
might see different results each time you run the program.

Managing mutable state in your app becomes a loaded task once you run
asynchronous concurrent code.

Foundation and UIKit/AppKit


Apple has been continually improving asynchronous programming for their
platforms over the years. They’ve created several mechanisms you can use, on
different system levels, to create and execute asynchronous code.

You can use APIs as low-level as managing your own threads with NSThread all the
way up to using Swift’s modern concurrency with the async/await construct.

You’ve probably used at last some of the following in your apps:

• NotificationCenter: Executes a piece of code any time an event of interest


happens, such as when the user changes the orientation of the device or when the
software keyboard shows or hides on the screen.

• The delegate pattern: Lets you define an object that acts on behalf of, or in
coordination with, another object. For example, in your app delegate, you define
what should happen when a new remote notification arrives, but you have no idea
when this piece of code will run or how many times it will execute.

• Grand Central Dispatch and Operations: Helps you abstract the execution of
pieces of work. You can use them to schedule code to run sequentially in a serial
queue or to run a multitude of tasks concurrently in different queues with
different priorities.

• Closures: Create detached pieces of code that you can pass around in your code,
so other objects can decide whether to execute it, how many times, and in what
context.

raywenderlich.com 22
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Since most typical code performs some work asynchronously, and all UI events are
inherently asynchronous, it’s impossible to make assumptions about which order the
entirety of your app code will execute.

And yet, writing good asynchronous programs is possible. It’s just more complex
than… well, we’d like it to be.

Certainly, one of the causes for these issues is the fact that a solid, real-life app most
likely uses all the different kinds of asynchronous APIs, each with its own interface,
like so:

Combine introduces a common, high-level language to the Swift ecosystem to design


and write asynchronous code.

Apple has integrated Combine into its other frameworks too, so Timer,
NotificationCenter and core frameworks like Core Data already speak its
language. Luckily, Combine is also very easy to integrate into your own code.

Finally, last but definitely not least, Apple designed their amazing UI framework,
SwiftUI, to integrate easily with Combine as well.

raywenderlich.com 23
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

To give you an idea of how committed Apple is to reactive programming with


Combine, here’s a simple diagram showing where Combine sits in the system
hierarchy:

Various system frameworks, from Foundation all the way up to SwiftUI, depend on
Combine and offer Combine integration as an alternative to their more “traditional”
APIs.

Swift’s Modern Concurrency


Swift 5.5 introduces a range of APIs for developing asynchronous and concurrent
code which, thanks to a new threading-pool model, allows your code to safely and
quickly suspend and resume asynchronous work at will.

The modern concurrency APIs make many of the classic async problems fairly easy
to solve - for example waiting on a network response, running multiple tasks in
parallel, and more.

These APIs solve some of the same problems as Combine does, but Combine’s
strength lays in its rich set of operators. The operators that Combine offers for
processing events over time make a lot of complex, common scenarios easy to
address.

raywenderlich.com 24
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Reactive operators directly address a variety of common problems in networking,


data processing, and handling UI events so for more complex applications there’s a
lot of benefit in developing with Combine.

And, speaking of Combine’s strengths, let’s have a quick look at reactive


programming’s excellent track so far.

Foundation of Combine
Declarative, reactive programming isn’t a new concept. It’s been around for quite a
while, but it’s made a fairly noticeable comeback in the last decade.

The first “modern-day” reactive solution came in a big way in 2009 when a team at
Microsoft launched a library called Reactive Extensions for .NET (Rx.NET).

Microsoft made that Rx.NET implementation open source in 2012, and since then,
many different languages have started to use its concepts. Currently, there are many
ports of the Rx standard like RxJS, RxKotlin, RxScala, RxPHP and more.

For Apple’s platforms, there have been several third-party reactive frameworks like
RxSwift, which implements the Rx standard; ReactiveSwift, directly inspired by Rx;
Interstellar, which is a custom implementation and others.

Combine implements a standard that is different but similar to Rx, called Reactive
Streams. Reactive Streams has a few key differences from Rx, but they both agree on
most of the core concepts.

If you haven’t previously used one or another of the frameworks mentioned above —
don’t worry. So far, reactive programming has been a rather niche concept for
Apple’s platforms, and especially with Swift.

In iOS 13/macOS Catalina, however, Apple brought reactive programming support to


its ecosystem via the built-in system framework, Combine.

With that said, start by learning some of Combine’s basics to see how it can help you
write safe and solid asynchronous code.

raywenderlich.com 25
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Combine basics
In broad strokes, the three key moving pieces in Combine are publishers, operators
and subscribers. There are, of course, more players in the team, but without those
three you can’t achieve much.

You’ll learn in detail about publishers and subscribers in Chapter 2, “Publishers &
Subscribers,” and the complete second section of the book guides you through
acquainting you with as many operators as humanly possible.

In this introductory chapter, however, you’re going to get a simple crash course to
give you a general idea of the purpose those types have in the code and what their
responsibilities are.

Publishers
Publishers are types that can emit values over time to one or more interested parties,
such as subscribers. Regardless of the internal logic of the publisher, which can be
pretty much anything including math calculations, networking or handling user
events, every publisher can emit multiple events of these three types:

1. An output value of the publisher’s generic Output type.

2. A successful completion.

3. A completion with an error of the publisher’s Failure type.

A publisher can emit zero or more output values, and if it ever completes, either
successfully or due to a failure, it will not emit any other events.

Here’s how a publisher emitting Int values could look like visualized on a timeline:

The blue boxes represent values that were emitted at a given time on the timeline,
and the numbers represent the emitted values. A vertical line, like the one you see on
the right-hand side of the diagram, represents a successful stream completion.

raywenderlich.com 26
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

The simple contract of three possible events is so universal that it could represent
any kind of dynamic data in your program. That’s why you can address any task in
your app using Combine publishers — regardless of whether it’s about crunching
numbers, making network calls, reacting to user gestures or displaying data on-
screen.

Instead of always looking in your toolbox for the right tool to grab for the task at
hand, be it adding a delegate or injecting a completion callback — you can just use a
publisher instead.

One of the best features of publishers is that they come with error handling built in;
error handling isn’t something you add optionally at the end, if you feel like it.

The Publisher protocol is generic over two types, as you might have noticed in the
diagram earlier:

• Publisher.Output is the type of the output values of the publisher. If it’s an Int
publisher, it can never emit a String or a Date value.

• Publisher.Failure is the type of error the publisher can throw if it fails. If the
publisher can never fail, you specify that by using a Never failure type.

When you subscribe to a given publisher, you know what values to expect from it and
which errors it could fail with.

Operators
Operators are methods declared on the Publisher protocol that return either the
same or a new publisher. That’s very useful because you can call a bunch of operators
one after the other, effectively chaining them together.

Because these methods, called “operators”, are highly decoupled and composable,
they can be combined (aha!) to implement very complex logic over the execution of a
single subscription.

raywenderlich.com 27
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

It’s fascinating how operators fit tightly together like puzzle pieces. They cannot be
mistakenly put in the wrong order or fit together if one’s output doesn’t match the
next one’s input type:

In a clear deterministic way, you can define the order of each of those asynchronous
abstracted pieces of work alongside with the correct input/output types and built-in
error handling. It’s almost too good to be true!

As an added bonus, operators always have input and output, commonly referred to as
upstream and downstream — this allows them to avoid shared state (one of the
core issues we discussed earlier).

Operators focus on working with the data they receive from the previous operator
and provide their output to the next one in the chain. This means that no other
asynchronously-running piece of code can “jump in” and change the data you’re
working on.

raywenderlich.com 28
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Subscribers
Finally, you arrive at the end of the subscription chain: Every subscription ends with
a subscriber. Subscribers generally do “something” with the emitted output or
completion events.

Currently, Combine provides two built-in subscribers, which make working with data
streams straightforward:

• The sink subscriber allows you to provide closures with your code that will receive
output values and completions. From there, you can do anything your heart
desires with the received events.

• The assign subscriber allows you to, without the need of custom code, bind the
resulting output to some property on your data model or on a UI control to display
the data directly on-screen via a key path.

Should you have other needs for your data, creating custom subscribers is even
easier than creating publishers. Combine uses a set of very simple protocols that
allow you to be able to build your own custom tools whenever the workshop doesn’t
offer the right one for your task.

raywenderlich.com 29
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Subscriptions

Note: This book uses the term subscription to describe both Combine’s
Subscription protocol and its conforming objects, as well as the complete
chain of a publisher, operators and a subscriber.

When you add a subscriber at the end of a subscription, it “activates” the publisher
all the way at the beginning of the chain. This is a curious but important detail to
remember — publishers do not emit any values if there are no subscribers to
potentially receive the output.

Subscriptions are a wonderful concept in that they allow you to declare a chain of
asynchronous events with their own custom code and error handling only once, and
then you never have to think about it again.

If you go full-Combine, you could describe your whole app’s logic via subscriptions
and once done, just let the system run everything without the need to push or pull
data or call back this or that other object:

raywenderlich.com 30
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Once the subscription code compiles successfully and there are no logic issues in
your custom code — you’re done! The subscriptions, as designed, will
asynchronously “fire” each time some event like a user gesture, a timer going off or
something else awakes one of your publishers.

Even better, you don’t need to specifically memory manage a subscription, thanks to
a protocol provided by Combine called Cancellable.

Both system-provided subscribers conform to Cancellable, which means that your


subscription code (e.g. the whole publisher, operators and subscriber call chain)
returns a Cancellable object. Whenever you release that object from memory, it
cancels the whole subscription and releases its resources from memory.

This means you can easily “bind” the lifespan of a subscription by storing it in a
property on your view controller, for example. This way, any time the user dismisses
the view controller from the view stack, that will deinitialize its properties and will
also cancel your subscription.

Or to automate this process, you can just have an [AnyCancellable] collection


property on your type and throw as many subscriptions inside it as you want. They’ll
all be automatically canceled and released when the property is released from
memory.

As you see, there’s plenty to learn, but it’s all logical when explained in detail. And
that’s exactly what the plan is for the next chapters — to bring you slowly but
steadily from zero to Combine hero by the end of this book.

What’s the benefit of Combine code over


“standard” code?
You can, by all means, never use Combine and still create the best apps out there.
There’s no argument about that. You can also create the best apps without Core Data,
URLSession, or even UIKit. But using those frameworks is more convenient, safe and
efficient than building those abstractions yourself.

raywenderlich.com 31
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Combine (and other system frameworks) aim to add another abstraction to your
async code. Another level of abstraction on the system level means tighter
integration that’s well tested and a safe-bet technology.

It’s up to you to decide whether Combine is a great fit for your project or not, but
here are just a few “pro” reasons you might not have considered yet:

• Combine is integrated on the system level. That means Combine itself uses
language features that are not publicly available, offering you APIs that you
couldn’t build yourself.

• Combine abstracts many common operations as methods on the Publisher


protocol and they’re already well tested.

• When all of your asynchronous pieces of work use the same interface — Publisher
— composition and reusability become extremely powerful.

• Combine’s operators are highly composable. If you need to create a new one, that
new operator will instantly plug-and-play with the rest of Combine.

• Combine’a asynchronous operators are already tested. All that’s left for you to do
is test your own business logic.

As you see, most of the benefits revolve around safety and convenience. Combined
with the fact that the framework comes from Apple, investing in writing Combine
code looks promising.

App architecture
As this question is most likely already sounding alarms in your head, take a look at
how using Combine will change your pre-existing code and app architecture.

Combine is not a framework that affects how you structure your apps. Combine deals
with asynchronous data events and unified communication contract — it does not
alter, for example, how you would separate responsibilities in your project.

You can use Combine in your MVC (Model-View-Controller) apps, you can use it in
your MVVM (Model-View-ViewModel) code, in VIPER and so forth and so on.

This is one of the key aspects of adopting Combine that is important to understand
early — you can add Combine code iteratively and selectively, using it only in the
parts you wish to improve in your codebase. It’s not an “all or nothing” choice you
need to make.

raywenderlich.com 32
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

You could start by converting your data models, or adapting your networking layer,
or simply using Combine only in new code that you add to your app while keeping
your existing functionality as-is.

It’s a slightly different story if you’re adopting Combine and SwiftUI at the same
time. In that case, it really does make sense to drop the C from an MVC architecture.
But that’s thanks to using Combine and SwiftUI in tandem — those two are simply on
fire when in the same room.

View controllers just don’t have any chance against a Combine/SwiftUI team. When
you use reactive programming all the way from your data model to your views, you
don’t need to have a special controller just to control your views:

If that sounds interesting, you’re in for a treat, as this book includes a solid
introduction to using the two frameworks together in Chapter 15, “In Practice:
Combine & SwiftUI.”

Book projects
In this book, you’ll start with the concepts first and move on to learning and trying
out a multitude of operators.

Unlike other system frameworks, you can work pretty successfully with Combine in
the isolated context of a playground.

raywenderlich.com 33
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Learning in an Xcode playground makes it easy to move forward and quickly


experiment as you progress through a given chapter and to see instantly the results
in Xcode’s Console:

Combine does not require any third-party dependencies, so usually, a few simple
helper files included with the starter playground code for each chapter will suffice to
get you running. If Xcode ever gets stuck while you experiment in the playground, a
quick restart will likely solve the issue.

Once you move to more complex concepts than playing with a single operator, you’ll
alternate between working in playgrounds and real Xcode projects like the Hacker
News app, which is a newsreader that displays news in real time:

raywenderlich.com 34
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

It’s important that, for each chapter, you begin with the provided starter playground
or project, as they might include some custom helper code which isn’t relevant to
learning Combine. These tidbits are pre-written so you don’t distract yourself from
the focus of that chapter.

In the last chapter, you’ll make use of all the skills you learned throughout the book
as you finish developing a complete iOS app that relies heavily on Combine and Core
Data. This will give you a final push on your road to building real-life applications
with Combine!

raywenderlich.com 35
Combine: Asynchronous Programming with Swift Chapter 1: Hello, Combine!

Key points
• Combine is a declarative, reactive framework for processing asynchronous events
over time.

• It aims to solve existing problems, like unifying tools for asynchronous


programming, dealing with mutable state and making error handling a starting
team player.

• Combine revolves around three main types: publishers to emit events over time,
operators to asynchronously process and manipulate upstream events and
subscribers to consume the results and do something useful with them.

Where to go from here?


Hopefully, this introductory chapter has been useful and has given you an initial
understanding of the issues Combine addresses as well as a look at some of the tools
it offers to make your asynchronous code safer and more reliable.

Another important takeaway from this chapter is what to expect from Combine and
what is out of its scope. Now, you know what you’re in for when we speak of reactive
code or asynchronous events over time. And, of course, you don’t expect using
Combine to magically solve your app’s problems with navigation or drawing on-
screen.

Finally, having a taste of what’s in store for you in the upcoming chapters has
hopefully gotten you excited about Combine and reactive programming with Swift.
Upwards and onwards, here we go!

raywenderlich.com 36
2 Chapter 2: Publishers &
Subscribers
By Marin Todorov

Now that you’ve learned some of the basic concepts of Combine, it’s time to jump in
and play with two of Combine’s core components — publishers and subscribers.

In this chapter, you’ll experiment with various ways to create publishers and
subscribe them so that you feel right at home when you need to do so throughout
the book.

Note: There are starter and final versions of the playgrounds and projects that
you’ll use in each of the chapters in this book. The starter is ready for you to
enter the code for each example and challenge. You can compare your work
with the final version at the end or along the way if you get stuck.

raywenderlich.com 37
Combine: Asynchronous Programming with Swift Chapter 2: Publishers & Subscribers

Getting started
For this chapter, you’ll use an Xcode playground with Combine imported. Open
Starter.playground in the projects folder and you’ll see the following:

Open Sources in the Project navigator (View ▸ Navigators ▸ Show Project


Navigator and twist down the Combine playground page), and select
SupportCode.swift. It contains the following helper function example(of:):

public func example(of description: String,


action: () -> Void) {
print("\n——— Example of:", description, "———")
action()
}

You’ll use this function to encapsulate each example you’ll work on in a plauyground
throughout the book.

However, before you begin playing with those examples, you first need to look at
publishers, subscribers and subscriptions in a bit more detail. They form the
foundation of Combine and enable you to send and receive data, typically
asynchronously.

Hello Publisher
At the heart of Combine is the Publisher protocol. This protocol defines the
requirements for a type to be able to transmit a sequence of values over time to one
or more subscribers. In other words, a publisher publishes or emits events that can
include values of interest.

The idea of subscribing a publisher is similar to subscribing for a specific notification


from NotificationCenter. With NotificationCenter you express interest in
certain events and then you’re notified asynchronously whenever a new event comes
through.

raywenderlich.com 38
Combine: Asynchronous Programming with Swift Chapter 2: Publishers & Subscribers

In fact, they are so similar, that NotificationCenter has a method named


publisher(for:object:) that provides a Publisher type that can publish
notifications.

To check this out in practice, go back to the starter playground and replace the Add
your code here placeholder with the following code:

example(of: "Publisher") {
// 1
let myNotification = Notification.Name("MyNotification")

// 2
let publisher = NotificationCenter.default
.publisher(for: myNotification, object: nil)
}

In this code, you:

1. Create a notification name.

2. Access NotificationCenter’s default instance, call its


publisher(for:object:) method and assign its return value to a local
constant.

Option-click on publisher(for:object:), and you’ll see that it returns a


Publisher that emits an event when the default notification center broadcasts a
notification.

So what’s the point of publishing notifications when a notification center is already


capable of broadcasting its notifications without a publisher? Glad you asked!

You can think of these types of methods as a bridge from the older async APIs to the
newer alternatives — a way to Combine-ify them, if you will.

A publisher emits two kinds of events:

1. Values, also referred to as elements.

2. A completion event.

A publisher can emit zero or more values but only one completion event, which can
either be a normal completion event or an error. Once a publisher emits a
completion event, it’s finished and can no longer emit any more events.

raywenderlich.com 39
Combine: Asynchronous Programming with Swift Chapter 2: Publishers & Subscribers

Note: In that sense, a publisher is somewhat similar to a Swift iterator. One


very valuable difference is that a Publisher’s completion could be either
successful or a failure, and also that you need to actively pull values from an
iterator, while a Publisher pushes values to its consumers.

Next, you’ll wrap up the current example by using NotificationCenter to observe


for and post a notification. You’ll also unregister that observer when you’re no longer
interested in receiving that notification.

Append the following code to what you already have in the example’s closure:

// 3
let center = NotificationCenter.default

// 4
let observer = center.addObserver(
forName: myNotification,
object: nil,
queue: nil) { notification in
print("Notification received!")
}

// 5
center.post(name: myNotification, object: nil)

// 6
center.removeObserver(observer)

With this code, you:

3. Get a handle to the default notification center.

4. Create an observer to listen for the notification with the name you previously
created.

5. Post a notification with that name.

6. Remove the observer from the notification center.

Run the playground. You’ll see this output printed to the console:

——— Example of: Publisher ———


Notification received!

The example’s title is a little misleading because the output is not actually coming
from a publisher. For that to happen, you need a subscriber.

raywenderlich.com 40
Combine: Asynchronous Programming with Swift Chapter 2: Publishers & Subscribers

Hello Subscriber
Subscriber is a protocol that defines the requirements for a type to be able to
receive input from a publisher. You’ll dive deeper into conforming to the Publisher
and Subscriber protocols shortly; for now, you’ll focus on the basic flow.

Add a new example to the playground that begins like the previous one:

example(of: "Subscriber") {
let myNotification = Notification.Name("MyNotification")
let center = NotificationCenter.default

let publisher = center.publisher(for: myNotification, object:


nil)

If you were to post a notification now, the publisher wouldn’t emit it because there is
no subscription to consume the notification yet.

Subscribing with sink(_:_:)


Continue in the previous example and add the following code:

// 1
let subscription = publisher
.sink { _ in
print("Notification received from a publisher!")
}

// 2
center.post(name: myNotification, object: nil)
// 3
subscription.cancel()

With this code, you:

1. Create a subscription by calling sink on the publisher.

2. Post the notification.

3. Cancel the subscription.

raywenderlich.com 41
Combine: Asynchronous Programming with Swift Chapter 2: Publishers & Subscribers

Don’t let the obscurity of the sink method name give you a sinking feeling. Option-
click on sink and you’ll see that it provides an easy way to attach a subscriber with
closures to handle output from a publisher. In this example, you just print a message
to indicate that a notification was received. You’ll learn more about canceling a
subscription shortly.

Run the playground and you’ll see the following:

——— Example of: Publisher ———


Notification received from a publisher!

The sink operator will continue to receive as many values as the publisher emits -
this is known as unlimited demand. And although you ignored them in the previous
example, the sink operator actually provides two closures: one to handle receiving a
completion event (a success or a failure), and one to handle receiving values.

To try those out, add this new example to your playground:

example(of: "Just") {
// 1
let just = Just("Hello world!")

// 2
_ = just
.sink(
receiveCompletion: {
print("Received completion", $0)
},
receiveValue: {
print("Received value", $0)
})
}

Here, you:

1. Create a publisher using Just, which lets you create a publisher from a single
value.

2. Create a subscription to the publisher and print a message for each received
event.

Run the playground. You’ll see the following:

——— Example of: Just ———


Received value Hello world!
Received completion finished

raywenderlich.com 42
Combine: Asynchronous Programming with Swift Chapter 2: Publishers & Subscribers

Option-click on Just and the Quick Help explains that it’s a publisher that emits its
output to each subscriber once and then finishes.

Try adding another subscriber by adding the following code to the end of your
example:

_ = just
.sink(
receiveCompletion: {
print("Received completion (another)", $0)
},
receiveValue: {
print("Received value (another)", $0)
})

Run the playground. True to its word, a Just happily emits its output to each new
subscriber exactly once and then finishes.

Received value (another) Hello world!


Received completion (another) finished

Subscribing with assign(to:on:)


In addition to sink, the built-in assign(to:on:) operator enables you to assign the
received value to a KVO-compliant property of an object.

Add this example to see how this works:

example(of: "assign(to:on:)") {
// 1
class SomeObject {
var value: String = "" {
didSet {
print(value)
}
}
}

// 2
let object = SomeObject()

// 3
let publisher = ["Hello", "world!"].publisher

// 4
_ = publisher
.assign(to: \.value, on: object)
}

raywenderlich.com 43
Combine: Asynchronous Programming with Swift Chapter 2: Publishers & Subscribers

From the top:

1. Define a class with a property that has a didSet property observer that prints the
new value.

2. Create an instance of that class.

3. Create a publisher from an array of strings.

4. Subscribe to the publisher, assigning each value received to the value property of
the object.

Run the playground and you will see printed:

——— Example of: assign(to:on:) ———


Hello
world!

Note: In later chapters you’ll see that assign(to:on:) is especially useful


when working on UIKit or AppKit apps because you can assign values directly
to labels, text views, checkboxes and other UI components.

Republishing with assign(to:)


There is a variation of the assign operator that you can use to republish values
emitted by a publisher through another property marked with the @Published
property wrapper. To try this add this new example to your playground:

example(of: "assign(to:)") {
// 1
class SomeObject {
@Published var value = 0
}

let object = SomeObject()

// 2
object.$value
.sink {
print($0)
}

// 3
(0..<10).publisher
.assign(to: &object.$value)
}

raywenderlich.com 44
Combine: Asynchronous Programming with Swift Chapter 2: Publishers & Subscribers

With this code, you:

1. Define and create an instance of a class with a property annotated with the
@Published property wrapper, which creates a publisher for value in addition to
being accessible as a regular property.

2. Use the $ prefix on the @Published property to gain access to its underlying
publisher, subscribe to it, and print out each value received.

3. Create a publisher of numbers and assign each value it emits to the value
publisher of object. Note the use of & to denote an inout reference to the
property.

The assign(to:) operator doesn’t return an AnyCancellable token, because it


manages the lifecycle internally and cancels the subscription when the @Published
property deinitializes.

You might wonder how is this useful compared to simply using assign(to:on:)?
Consider the following example (you don’t need to add this to the playground):

class MyObject {
@Published var word: String = ""
var subscriptions = Set<AnyCancellable>()

init() {
["A", "B", "C"].publisher
.assign(to: \.word, on: self)
.store(in: &subscriptions)
}
}

In this example, using assign(to: \.word, on: self) and storing the resulting
AnyCancellable results in a strong reference cycle. Replacing assign(to:on:) with
assign(to: &$word) prevents this problem.

You’ll focus on using the sink operator for now, but you’ll learn more about the use
of @Published properties in Chapter 8, “In Practice: Project “Collage”,” and in later
chapters.

raywenderlich.com 45
Other documents randomly have
different content
die Lektionen —. Ich habe mich bemüht, es so gut zu machen, wie
ich nur konnte: und da hat das Wenige genügt, — da haben diese
anderthalb Gedanken schon genügt, — um alle Kraft aufzuzehren —.
Oder hatte ich nicht genug Kraft — —?«
Und langsam sank die Bitterkeit von ihrer Seele, um nur einer
tiefen, demütigenden Entmutigung den Platz zu lassen. Bitterkeit
vermochte ihre Seele nicht lange zu ertragen: die Entmutigung nahm
sie schweigend auf.
Als die Mädchen sahen, daß die Mutter nicht recht heiter gestimmt
war, schoben sie es auf die Ermüdung durch den anstrengenden Tag,
und unwillkürlich suchten sie ihre eigne Fröhlichkeit etwas zu
dämpfen, die sich mitunter allzuhell Luft machte.
Marianne merkte es, und das Herz zog sich ihr zusammen. »Sie
wagen nicht mehr, mir zu zeigen, wie glücklich sie über die Wendung
der Dinge sind, — sie fürchten mich damit zu kränken, — sie
verhalten es lieber vor mir, bis sie unter sich sind,« dachte sie.
Und die kleinen Zärtlichkeiten ihrer Kinder thaten ihr nur weh. Sie
fühlte etwas Nachsichtiges aus allem heraus, — etwas Absichtliches.
Nein, lieber noch wollte sie es sein, die sich vor ihnen verstellte, und
mit ihnen froh sein.
Aber sie konnte es nicht.
Am nächsten Morgen beim Frühstückstisch wurde Cita doch trotz
Mariannens Bemühungen stutzig. Sie meinte so genau zu wissen,
daß die Mutter heute fast keine Lehrstunden mehr zu geben habe,
und dabei schien sie sich doch so zu beeilen, um nur fortzukommen.
Marianne behauptete sogar, sie könne noch nicht zum zweiten
Frühstück zurück sein, sondern erst spät am Nachmittag, sie
möchten nicht auf sie warten.
Sophie machte ein pfiffiges Gesicht, offenbar hatte Ma heimliche
Weihnachtsbesorgungen vor. Aber Cita blickte stumm und mit einem
zweifelnden, besorgten Ausdruck vor sich nieder. Wohin ging die
Mutter? Und warum sah sie dabei so gequält und müde aus? Ging
sie vielleicht, um wieder mit Tomasow etwas zu besprechen? Und
diesmal vielleicht etwas, womit sie ihren Kindern Leid anthat —?
Ach, ginge sie doch nicht zu ihm! — —
Marianne atmete tief auf, als sie endlich auf der Straße stand.
Langsam machte sie einen weiten Gang im klaren Winterwetter,
dann raffte sie sich zu einem Besuch bei einer aus dem Schuldienst
scheidenden Kollegin auf, von der sie sich erst in den Feiertagen
hatte verabschieden wollen. So kam allmählich die Zeit für die
einzige Stunde heran, die sie heute geben mußte.
Dabei weilten ihre Gedanken zu Hause. Alle Räume ihrer kleinen
Wohnung durchschritt sie, aber, als sei ihr Blick verhext, erschienen
sie ihr alle schon öde und leer. Sie erwog schon, wo, — in welchem
Raum, an welchem Platz — sie wohl sitzen würde, so ganz allein —.
Kleinigkeiten erwog sie angestrengt: ob man die hohen
Blattpflanzen, ihre Lieblinge, nicht fortgeben sollte, da sie nicht auf
ihre Pflege achten konnte, wenn sie so von Stunde zu Stunde
lief — —.
Von ihrer einzigen Unterrichtsstunde wäre Marianne fast aus
Zerstreutheit nach Hause gegangen. Plötzlich fiel ihr jedoch der
Weihnachtsbaum ein, der sich so groß und anspruchsvoll mitten in
ihrem Zimmer erhob, — als erwarte er sie da förmlich mit
herausforderndem Hohn. — — Morgen war schon heiliger Abend. Da
würde man ihn sogar noch schmücken müssen. Denn das wollten
die Mädchen ja ihretwegen gern thun, obschon es ihnen ein bißchen
lästig war, — sie selbst hielten nichts auf solche Kindereien —.
Wie recht sie hatten! Wie froh wäre sie jetzt gewesen über ein
sang- und klangloses Weihnachten!
Nein, sie vermochte nicht heimzugehn und sich an den gedeckten
Frühstückstisch zwischen ihre beiden Kinder hinzusetzen —.
Frierend und unschlüssig, wie obdachlos, stand Marianne auf der
Straße im Winterwinde.
Sie, die sich so auf die Ferien gefreut hatte, sie, die es so haßte,
sich Tag für Tag draußen herumtreiben zu müssen, sie stand jetzt
da, um den Ihrigen Lehrstunden vorzutäuschen, die sie gar nicht zu
geben hatte —.
Einmal fiel sie durch ihr zauderndes Stehnbleiben auf. Irgend ein
Straßenflaneur beugte sich vor, um sie deutlicher zu sehen —. Es
war mitten im Menschengetriebe unweit der Schmiedebrücke;
Marianne durchquerte den Fahrdamm, um in eine der stillern
Seitenstraßen einzubiegen, als sie zwischen den dahinhastenden
Menschen Tomasows Gestalt erkannte.
Er schritt langsam neben irgend einem Bekannten. Als er Marianne
auf sich zukommen sah, verabschiedete er sich jedoch von ihm und
ging ihr erfreut entgegen.
Leise schob sie ihren Arm in den seinen.
»Danke!« sagte er lächelnd. »— Offenbar auf Weihnachtswegen?«
Sie schüttelte den Kopf.
»Nein. Ich bin todmüde. Ich möchte irgendwo eintreten, wo ich
etwas essen könnte.«
»Sie wollen nicht erst den langen Weg nach Haus?« Er besann
sich. »Gehen wir zu Philippow? Oder ziehen Sie ein Restaurant vor?«
»Keins von beiden. Ueberall könnten Bekannte sein. Ich möchte
dort in der Seitenstraße in eine der kleinen billigen Theebuden, wo
kein Mensch hinkommt.«
Sie suchte ihn die paar Schritt weit hinzulenken.
»Aber, Ma! Da geht man mit einer Dame nicht hin.«
Marianne ließ geschwind seinen Arm los.
»— Dann lassen Sie mich allein hingehen — Ich nahm wirklich zu
dem Zweck Ihre Begleitung an,« sagte sie und blickte aus so
sonderbar müden Augen auf ihn, daß er sofort nachgab.
Er zuckte die Achseln.
»Nun es sei, also wie Sie wünschen,« meinte er zögernd und
führte sie dem kleinen Lokal zu, das mit einem breiten grellblauen
Schild zum Eintritt lud. »Schließlich ist es eine warme Ecke, wie eine
andre, wenn sie auch ein bißchen tief im Erdgeschoß drin liegt.«
Im Innern der Theestube hingen blendend saubere
Leinwandvorhänge an den niedrigen, fast quadratischen
Fensterchen, und auch das weiße Holz der simpeln Einrichtung sah
so weiß und sauber aus, als müsse es Seifengeruch ausströmen. Im
ersten Raum dampften ein paar mächtige blanke Kupfersamoware
auf dem Schenktisch, und an den Wänden lagen bis hoch hinauf
unendlich viele Schwarzbrote aufgestapelt.
Doch gab es auf Wunsch auch helles Gebäck, sowie die
volkstümlichen Pastetchen mit Grützfüllung, und Tomasow bestellte
davon, dessen sicher, sie vorzüglich bereitet zu finden. Der
bedienende Gehilfe im weißen Leinwandkittel und hohen, dermaßen
glänzend gewichsten Kniestiefeln, daß man sich in ihnen beinahe
hätte spiegeln können, brachte das Verlangte in den schmalen
Nebenraum, wo Marianne schon im Hintergrunde an einem der
länglichen ungestrichenen Holztische saß.
Nur zwei Frauen aus dem Kleinbürgerstande, mit bunten
Kopftüchern und kurzen Schaffellpelzen, tranken beim Fenster ihren
Thee, wobei sie die gefüllte Untertasse auf den gespreizten Fingern
der rechten Hand balancierten; schweigend, mit einer gewissen
Feierlichkeit und ohne um sich zu sehen, nahmen sie einen heißen
Schluck um den andern.
»Hier ist es gut!« sagte Marianne.
Sie sah abgespannt aus, und dabei brannte ihr das Gesicht vom
Winde. Die Hitze, die der mächtige Kachelofen im geschlossnen
Zimmerchen ausströmte, machte es noch fühlbarer.
Marianne empfand wirklichen Hunger, er war ganz plötzlich und
fast mit Gier erwacht, als sie beim Eintreten das viele ringsum an
den Wandborten aufgeschichtete Brot sah. Aber wie nun ihr
Frühstück vor ihr stand, vermochte sie ebenso plötzlich nichts mehr
zu essen.
Sie bückte sich über ihr Theeglas, aus dem dicht vor ihrem Gesicht
der Dampf in die Höhe stieg, und folgte mit dem Blick gedankenlos
seinen Windungen. Dieses Gefühl von sich nachgebender Schwäche
war merkwürdig angenehm.
Tomasow betrachtete sie aufmerksam.
»Sie gefallen mir ganz und gar nicht!« äußerte er; »aber eigentlich
hätt ich mir das ja schon vorgestern selbst voraussagen können —«
Marianne hob verwundert den Kopf.
»Was denn —?« fragte sie zerstreut.
»Daß der erste Kraftaufwand nicht vorhalten, — daß die Stimmung
zunächst sinken würde —. Sie haben sich seelisch bis zum äußersten
anspannen müssen, und jetzt kommt der Rückschlag.«
Marianne rührte mit ihrem Löffel im Thee herum. Ihr fiel ein, daß
Tomasow ja so gar nichts vom gestrigen Tage wußte. Ueberhaupt
nichts von der heimlichen Hoffnung, die sie ja allein so tapfer hatte
erscheinen lassen, — noch auch von der großen Bitterkeit hinterher.
Es war etwas ganz Ungewohntes für sie, daß er nicht vollen
Bescheid wußte und dementsprechend urteilte. Aber nur nicht davon
erzählen! Sogar ihm nichts! Was konnt es denn helfen?
Tomasow stützte einen Arm auf, und sich näher zu Marianne
hinwendend, mit dem Rücken gegen das Fenster, bemerkte er
halblaut: »Frau Marianne, jetzt ist es an der Zeit, daß Sie mir mehr
Machtvollkommenheit geben —. Vollmacht, Sie ganz anders als
bisher in Obhut zu nehmen, zu pflegen, abzulenken, zu
beaufsichtigen, — kurz: um Sie zu sein —«
Sie faßte seine Worte nur ungenau auf, in ihre Kümmernisse
klangen sie aus solcher Ferne herein, daß sie keinerlei verborgenen
Sinn hinter ihnen vermutete.
»Ich weiß, Sie sind immer gut!« sagte sie nur freundlich.
»— Gut —?! Nein, Marianne, mit meinem Gutsein hört es nun auf.
Glauben Sie nur, es ist mir nicht immer leicht gefallen ›gut‹ gegen
Sie zu sein, Ihr guter Freund zu sein — alle die Jahre. Jetzt aber, wo
Sie allein bleiben, wo sich Ihre Töchter ihr eignes Leben bauen, da
will ich ein andres Recht, als das der Güte: das Recht, auch ein
Leben aufzubauen — Ihnen und mir.«
Er sprach noch immer halblaut, jedoch rasch und bestimmt, und in
seiner Stimme vibrierte tief gedämpft ein Ton, den er Marianne
gegenüber noch nie angeschlagen hatte.
Sie schrak aus ihrer Müdigkeit auf, ihr Blick streifte Tomasow wie
erwachend und noch verständnislos erstaunt; als sie jedoch dabei
seinen fest auf sie gerichteten Augen begegnete, geriet sie in
Verwirrung.
Tomasow sagte fast gütig: »Es ist schlecht von mir, daß ich Sie so
überfalle, Ma —. Aber es hilft nun nichts mehr: bei Ihnen zu Hause
bin ich mit Ihnen tausendmal weniger allein als hier, — und im
nächsten Augenblick stehn Sie wieder lächelnd und gewappnet da,
— in jeden Arm hineingeschmiegt eins Ihrer Kinder. — — Sie sollen
mir auch nicht antworten müssen, Ma. Heute nicht und selbst
morgen nicht, wenn Sie wollen. Nur wissen, — wissen, daß Sie
keineswegs so selbstherrlich allein dastehn werden, wie Sie wohl
glauben, — — weil ich Sie mir nunmehr nehme —«
Marianne sah nicht auf. Die Röte auf ihren Wangen hatte sich
vertieft, als ob sie wieder den Wind draußen um sich sausen fühle.
Sie sprach sich innerlich die Worte vor, die sie Tomasow jetzt
zweifellos sagen mußte, — sie nahm sich vor, den Kopf zu heben
und ihn einfach zu bitten, — ja, zu bitten, er möchte doch wieder,
ganz so wie bisher, gegen sie »gut« sein —.
Aber nach seiner Bemerkung, daß er keine Antwort erwarte,
beugte sie den Kopf nur noch tiefer, und mit einem seltsamen Gefühl
von Beklemmung erließ sie sich alles, um was sie bitten wollte.
Denn bei dem Ton seiner Stimme, da quoll langsam, unvermutet
und betäubend eine wunderseltsame Gemütswallung in ihr auf — —.
Und machte sie zaudern, und ließ sie verwirrt den Blick Tomasows
meiden, wie wenn eine geheime Sehnsucht etwas ganz andres
ersehnt habe, als alle jemals bewußt gewordenen Gedanken in ihr.
— — Es war grade, als risse Tomasow mit ein paar gewaltsamen
Griffen den Vorhang von irgend einer fremden Landschaft zurück,
sodaß ihr plötzlich bewußt werden sollte: nur ein Vorhang scheide
sie davon —.
Sie meinte noch nie durch diese Landschaft gewandelt zu sein und
wußte doch auf einmal: nur ganz durchsichtig verhangen war sie ihr
gewesen, und immer da war sie gewesen, dicht vor ihr. Und
blitzschnell, zu neuem, verwirrendem Wiedererkennen, drängte sich
plötzlich vor ihrem Auge Bild auf Bild daraus. Minuten, Momente aus
ihrem Verkehr mit Tomasow sah sie vor sich, — oft unterbrochen
durch Monate und weit länger, oft einander rascher folgend in
feinen, unmerklichen Sensationen, — auf die sie mit dem Finger
hätte weisen können: da — und da — und da, — ja, war sie da
seinen Wünschen nicht, ohne es zu wissen, ganz nah gewesen, —
ganz nah einem weiblichen, eignen Glücksverlangen —?
Marianne saß regungslos und noch immer im Bann der leichten
Mattigkeit, die sie heute umfing. Allmählich vermischte sichs ihr
ganz, wo und wozu sie sich hier befand, tief benommen von der
Gemütsbewegung, die Macht über sie gewann. Sie fühlte sich wie
jemand, der ganz unvermutet geweckt wird und in völlig
irreführender Gegend zum Erwachen kommt. — —
Tomasow war ebenfalls verstummt. Nur sein Blick ruhte immer
wieder auf Marianne und mochte ihm einiges von dem enträtseln,
was in ihr vorging.
Ohne daß sie miteinander sprachen, ohne daß sie einander auch
nur anschauten, leitete sich zwischen ihnen eine Verwandlung ihres
gegenseitigen Verhältnisses ein: das nahm er mit allen Nerven wahr.
Und auch er überließ sich einem Hinträumen, das ihn weit fort
entführte — —.
Das Blut stieg ihm in die Schläfen, und seine Augen bekamen
einen eigentümlichen starken Glanz.
Ganz still war es in dem kleinen heißen Zimmer. Ein einziges Mal
ging draußen im Vorraum kreischend die Außenthür, ein paar
schwere Tritte, kurze Frage und Antwort, Papierknistern, und wieder
wurde alles still.
Die beiden Frauen am Fenster hatten sich erhoben, rückten ihre
Kopftücher zurecht und gingen auf knarrenden Schuhen mit
wortlosem Gruß hinaus.
Da blickte Marianne auf, fast verstört. Unmittelbar darauf erhob
sie sich schon. Die dumpfe, schwere Ofenluft benahm ihr den Atem.
»— Sie wollen gehn?« fragte Tomasow und half ihr in den Pelz.
»— Wollen Sie nichts weiter genießen?«
Marianne schüttelte stumm den Kopf. Sie schien zu meinen: jetzt
an die freie Luft draußen gelangen, das hieße zugleich, den ganzen
Bann und Druck abschütteln. Diese heiße Stubenschwüle war allein
schuld —.
Tomasow zahlte, und sie entfernten sich. Der Ostwind blies ihnen
auf der Straße scharf, förmlich wehethuend entgegen, er weckte fast
ein Gefühl unwillkürlichen Sichbergenwollens.
»Wohin nun?« fragte Tomasow, »muß es schon heimwärts gehn?«
Marianne nickte zögernd.
»Den Kreml durchqueren,« meinte sie, »das ist wohl der nächste
Weg.«
»— Und wärs auch nicht der nächste! Denn allzu kurz darf er nicht
geraten,« bemerkte er lächelnd.
Beim Ueberschreiten des Fahrdamms, zwischen den
durcheinander sausenden Schlittengespannen, hatte er Marianne
den Arm gegeben und führte sie mit der sichern Haltung dessen, bei
dem sie sich von nun an bergen sollte. Oder empfand nur sie es so,
als ob alles um eine Nuance verändert sei, als ob in allem schon eine
stillschweigend anerkannte Zueinandergehörigkeit betont liege —.
Eben begann Tomasow Marianne von seiner Liebe zu reden, da
traten sie schon in das Erlöserthor ein, das in den Kreml hineinführt.
Die Fuhrwerke mäßigten den Schritt, die Menschen entblößten ihr
Haupt, und Tomasow, der mechanisch seinen Hut abnahm, konnte in
der um sie eingetretenen Stille nicht recht weitersprechen.
Dann kamen sie auf den weiten Platz hinaus, vorüber an den
Kathedralen und dem alten Facettenpalast. Er schaute hin, und ihm
fiel eine kleine Zeichnung von Rjepin zu dessen Gemälde »Die
Brautwahl« ein, — ja, so hätte er um Ma freien mögen: inmitten der
Pracht der alten Palasträume, der niedrigen Wölbungen russischer
Terems, als der alten Fürsten einer —. Und er dachte zurück: noch
sein Großvater hatte sich seine Bäuerin vom Feld in die Hütte
geführt, und die geschmückten Dorfmädchen tanzten zur Hochzeit.
Ja, Hütte oder Palast, das war fast das gleiche: in beiden Fällen ward
der Mann der Fürst, der Herr vor seinem Weibe, das von ihm sein
Leben empfing.
Vor Tomasows unruhig umherblickenden Augen erhob sich der
Uspenski-Dom in der energischen Schlichtheit seiner männlich
gedrungenen Architektur, die grauen Kuppeln gleich Heldenhelmen
auf Heldenhäuptern, ohne andern Schmuck, andre Farbe, als die
verwitterten Bilder unter dem dunkeln Bleidach über dem Thor. Und
davor, wie in sich selbst zusammengeschmiegt, in festlicher Anmut,
die reizende Verkündigungskirche, die Vielkuppelige, die aussieht, als
bildete die Gliederung ihrer Mauern nur eben soviele Vorwände, um
eine stillleuchtende Kuppel nach der andern über sich
emporzuhalten. Wie Weib und Mann standen die beiden in
Tomasows Phantasie zusammen, die überall Symbole dessen
schaute, wovon sie aufgeregt erfüllt war.
Den Kopf gesenkt, ging Marianne neben ihm, ihren Blick immer
auf den flimmernden Schnee am Boden gerichtet, wie wenn sie mit
geblendeten Augen was ablese von dem weißen Geglitzer mit seinen
bläulichen huschenden Schatten und Lichtern.
Ihre Hand ruhte im Arm Tomasows; ein wenig zu ihr vorgebeugt,
unterhielt er nun Marianne mit halber Stimme. Unruhevoll schweiften
ihre Gedanken um das, was er zu ihr sprach. Kaum vermochte sie es
aufzunehmen in den einzelnen Sätzen, in den verhaltenen Worten,
so stark wirkte es seiner Grundbedeutung nach auf sie —. Ihr ward
beklommen wie in der kleinen dumpfen Gaststube vorhin; die
Schwüle blieb — —.
Führte er sie nicht hinauf auf einen Berg und zeigte ihr der Welt
Herrlichkeit, — jene Herrlichkeit, die man zu eignem Genießen haben
kann, in der man sich selbst leben kann, sich sättigen in allem
Angenehmen und Erfreulichen des Daseins? Führte er sie nicht
hinweg aus der Alltagsniederung mit ihrer einseitigen, bittern
Mühsal, mit den armseligen paar Aufgaben, die ihre Kraft
aufgesaugt, sie gedemütigt und unfähig gemacht hatten zu eigner,
breiterer Entfaltung? — — Und wieder schaute sie bei Tomasows
Worten wie in lockende Weiten, in eine Landschaft hinein, seltsam
fremd, seltsam vertraut, in der sie sollte ausruhen dürfen an
labendem Glück, sich gehn lassen in süßer Ermattung, — und seine
Stimme verhieß ihr fort und fort: wolle nur, und all dies ist dein —.
Sie überschritten grade den Platz, als ein erster tiefer
Glockenklang mit überwältigender Gewalt die Luft durchhallte.
Unmittelbar darauf setzte das Geläute von mehreren großen Glocken
ein. Es that den Menschen kund, daß die Feierzeit nahe, daß sie das
Werkzeug niederlegen möchten und die Seele öffnen, auf daß auch
sie feiere.
Und in Mariannens Seele wiederhallte es in einer lauten Bejahung:
sie sehnte sich, zu feiern —.
Aber gleichzeitig klangen mit den Glockenklängen ganz andre
Stimmungen als zuvor in ihr an, sie kam heim von ihren ungewiß
schweifenden Träumereien, zurück in die Gegenwart ihres wirklichen
Lebens, und — wie zwei, die sie gewaltsam hatte vergessen wollen,
— schauten ihr die Gesichter ihrer beiden Kinder fragend daraus
entgegen —.
Fragend, — so wie heute morgen: Sophiens Gesicht dabei ein
wenig verschmitzt, voll pfiffiger Erwartung, beinahe wie sie auch als
kleines Kind ausgesehen hatte, wenn die Heimlichkeiten um
Weihnachten begannen. Citas Augen fragten nicht mehr kindlich:
bringst du mir auch was Schönes mit? Sie hatte sorgenvoll vor sich
hingeblickt, — zweifelnd fast, — sie war beunruhigt durch das
Benehmen der Mutter. Und wenn sie jetzt erfuhr, — Cita —
Mariannens Herz that plötzlich einen starken, harten Schlag. Sie
blieb stehn, wie atemlos: wenn Cita erfuhr — und auch Sophie — —,
sie sah mit einem Schlage die beiden Gesichter verwandelt, bestürzt,
ungläubig —, sie fühlte mit unwiderleglicher Deutlichkeit: dann erst
entfremdeten sich ihr die Kinder ganz —.
Alles Entfremden bisher bedeutete, dagegen gehalten, noch
wenig, — wie weh es auch thun mochte, es mußte machtlos bleiben,
solange die Mutter selbst nur ihren Mädchen dieselbe blieb. Auch
wenn sie Tausende von Meilen weit fort von ihr gingen: sie
entfernten sich weniger weit, als durch einen einzigen Schritt, den
sie selber fort von ihnen that.
»— Die Kinder —!« sagte Marianne unwillkürlich, mitten in
Tomasows Worte hinein, und sie hob zum erstenmal den Blick zu
ihm, — ratlos, hilfeheischend. War er doch da, ging er doch neben
ihr, — er, der immer alles entschieden, bei allem helfend eingegriffen
hatte.
Voll Zuversicht schaute sie zu ihm auf.
»Was ist denn mit den Kindern?« fragte er etwas brüsk, aus der
Stimmung gerissen; seine Augen begegneten den ihren mit
eigentümlichem, flackerndem Leuchten, »— es handelt sich jetzt
doch gar nicht um die Kinder.«
Mariannens Blick glitt rasch, betroffen von ihm ab. Wer half ihr
von nun an in allen Fragen und Kämpfen? Er nicht mehr! Er half ihr
nicht mehr gegen ihre eignen Schwächen. Bisher konnte er sich ihr
so geben, wie sie ihn brauchte, um sich als Mensch hoch und höher
emporzuringen. Jetzt, ohne alle Zurückhaltung, brauchte er sie
selbst, brauchte sie ohne die Kinder. Wie weit, — weit standen ihm
da ihre Herzenssorgen —!
Irgend etwas in Marianne, irgend ein eben erst entfachtes, eben
erst wiedererwachtes Sehnen des Weibes in ihr verschüttete sich
wieder und wollte zagend erlöschen —.
Tomasow fühlte sofort, daß er einen Fehler begangen habe.
»Alles hat seine Zeit!« sagte er schnell und bestimmt. »Auch die
Kinder haben ihre Zeit gehabt, wo Sie sich ihnen ausschließlich
widmeten. Nun ist es endlich Zeit geworden, in diesem Punkt
vernünftig umzulernen. Schließlich muß man eben wählen, ob man
einander leben will und dem Glück, oder ob man von ihrem unreifen
Willen abhängen will.«
Und mit größerer Dringlichkeit als vorher sprach er auf sie ein,
indessen sie weitergingen im hallenden Glockengeläut, vorbei an den
weißgoldenen Mauern der zahllosen Kirchen und Kathedralen. Und je
länger er redete, desto mehr wurde es eine Apotheose des sorglosen
Feierns und Genießens, wozu er sie einlud. Er suchte alles hervor,
was er ihr schenken könnte, und alles ward immer wieder Genuß
und Fest. Aber Mariannens Hand lag nur ganz leicht in seinem Arm,
sie stützte sich nicht mehr auf ihn, sie sah unruhig aus, und aus
ihrem Gesicht war die gläubige Zuversicht geschwunden.
Und Tomasow überfiel plötzlich eine zornige, bittere Ungeduld
wider alles, was er da selbst zu Marianne sprach. Alle die Worte von
Glück und Freude erschienen ihm unwahr und schal. Er begriff
plötzlich, daß er, an Mariannens Seite, doch immer nach einem
suchen würde, nach eben dieser emporschauenden Zuversicht, nach
eben dieser gläubigen Anlehnung an ihn, als an einen Stärkern,
Ueberlegenen, — an den Herrn. Glück mit ihr genießen, das konnte
nur heißen: ihr im Leben selber so hoch und stark als Mensch
überlegen sein, wie er ihrs in einzelnen Stunden durch Verstand und
Rat gewesen war —.
Tomasow verstummte.
Und Marianne merkte es kaum. Wie sie so an seinem Arm hinging,
schienen ihr jetzt die Glocken über ihr mit den weithin hallenden
Feierklängen nicht mehr dieselbe Sprache zu sprechen, wie die
dringliche Stimme dicht an ihrem Ohr, — aus einer andern Welt
schienen sie zu reden, als dies halblaute überredende Raunen von
Feiertagsglück und abgeworfenen Sorgen —. Und immer mächtiger
wurden die Glockenklänge und immer verhaltener die zuredende
Stimme, und endlich vernahm sie nur noch Glocken, — Glocken
allein — —.
»— Leben Sie wohl, Ma!« hörte sie unvermittelt Tomasow sagen,
der stehn blieb. »Ich habe Ihre Antwort schon, noch ehe Sie eine
Antwort in Worten gefunden haben. Und lassen Sie mich bekennen:
Sie haben recht —«
»Tomasow,« fiel Marianne tief bewegt ein, »— warum wollen Sie
so — —! — Sie sind immer und immer mein bester, einziger, liebster
Freund —«
»— Gewesen!« ergänzte er rasch mit einem unmerklichen
Lächeln, und dann, sich umsehend, trat er zur Seite. Es kam jemand
von hinten her an ihnen vorbei und zog grüßend den Hut.
Hugo Lanz war es, der desselben Weges ging und Marianne
hocherfreut begrüßte. Marianne mußte ihn Tomasow vorstellen.
»Ich eilte grade zu Ihnen, gnädige Frau,« bemerkte Hugo Lanz,
»um Ihnen eine für mich freudige Nachricht mitzuteilen —«
»Das trifft sich in der That gut,« meinte Tomasow etwas heiser,
»daß ich mithin die gnädige Frau in Ihrer Begleitung lassen kann.
Mein Weg führt hier leider nach andrer Richtung.«
Marianne reichte Tomasow die Hand, zögernd, fast zitternd.
»— Aber doch auf Wiedersehen sehr bald —?« fragte sie mit nicht
ganz beherrschter Stimme.
»Gewiß, gnädige Frau: sobald sich einmal gute Bekannte bei
Ihnen versammeln, dann gestatten Sie mir vielleicht, auch dabei zu
sein,« entgegnete er mit leichter Betonung dieser Antwort, beugte
sich über ihre Hand, grüßte Hugo Lanz und entfernte sich, in die
nächste Straße einbiegend.
Marianne ging statt vorwärts wieder zurück, ohne recht zu wissen
und zu sehen, wo sie ging. Ein Angstgefühl umklammerte sie dumpf:
sie konnte nicht fassen, daß das ein Abschied für das Leben
gewesen war.
Sie machte eine gewaltsame Anstrengung, um sich Hugo Lanz
zuzuwenden, dessen offnes Gesicht von Freude geleuchtet hatte, der
aber jetzt ernst und still aussah, weil er sie so seltsam ernst vor sich
hin gehn sah.
Er erzählte dennoch froh: »Soeben erst hab ich die Erlaubnis
ausgewirkt, den nächsten Winter noch ganz frei zu bleiben, — und
ich werde ihn hier zubringen. Meine Verwandten haben mich
aufgefordert, bei ihnen zu wohnen. Und schon die Aussicht, Sie und
Ihre Familie besuchen zu dürfen —«
»Das freut mich innig,« bemerkte Marianne leise, »doch werden
Sie im nächsten Winter nur noch mich wiederfinden, — nicht mehr
meine Töchter. Auch Sophie geht fort, folgt der Schwester ins
Ausland.«
Hugo Lanz blickte Marianne mit aufrichtigem Schreck ins Gesicht.
Die kleine Familienscene, der er beigewohnt hatte, stand vor ihm,
Mariannens strahlendes Glück zwischen ihren Kindern, — auch
dessen, was ihm Sophie mitgeteilt hatte, entsann er sich.
»— Ganz allein bleiben Sie —?« entfuhr es ihm voll Mitleid und in
unwillkürlichem Unwillen.
Marianne wiederholte mechanisch: »— Allein —,« und sie nickte
bejahend. Aber das dumpfe Angstgefühl in ihr verstärkte sich dabei,
als risse es sie mit jedem Schritt gewaltsamer hinein in etwas
Endloses, Grenzenloses, — wie in eine leere, gähnende
Unermeßlichkeit, wo ihre Kinder und der Freund und alles, was ihr
lieb gewesen war, alles Warme, alles Trostvolle, alles Hilfreiche,
weiter und immer weiter zurückwich, — unerkenntlich geworden
schon, — unaufhaltsam, unerreichbar — —.
Und mit dunkelm Grauen stieg in ihrer Seele eine Erinnerung auf
an abgrundtiefe Einsamkeit, aus der sie doch nur die Hand des
Freundes und der Blick ihrer Kinder gerettet hatte, — und sie fühlte,
daß das dunkle Grauen nahe und näher über ihrer Seele
zusammenschlug, — als würde sie unbarmherzig dahinein gestoßen
von derselben Hand, von denselben Blicken, die sie einst rettend
festhielten, — und als fände sie diesmal nie mehr, — nie mehr
hinaus —.
Marianne nahm nichts mehr deutlich wahr, die Dinge ringsum
schienen ihr langsam zu entschwinden, sich in sich selbst
aufzutrinken, unterzugehn in einem chaotischen Nebel. Einförmig
nur und erschütternd laut hallten fort und fort die Glocken über ihr,
— hallten um sie, — hallten in ihr, — begruben sie wie unter einem
Mantel von dröhnenden, besinnungraubenden Tonwellen, — ließen
alles an ihr erbeben unter der Gewalt des einen unerbittlichen
Klanges, — drangen auf ihre zitternde Schwäche ein, wie mit
läutenden Unendlichkeiten — —
Marianne war, einer Ohnmacht nahe, stehn geblieben und rang
nach Atem.
Sie standen wieder dicht vor der Verkündigungskirche, an den
Stufen, über denen sich die Eingangspforte erhebt. Hugo Lanz hatte
einen Arm um Marianne gelegt und führte sie, sie vorsichtig
stützend, hinauf bis in den Seitengang, wo längs den Fensterchen
von gewelltem Glas eine Bank stand.
Dort ließ er Marianne niedersitzen und neigte sich, neben ihr stehn
bleibend, mit besorgter Frage zu ihr.
Aber sie achtete nicht auf das, was er flüsternd fragte. Dicht vor
ihr öffnete sich das blausilberne Portal in den innern Kirchenraum,
auf der Seite, wo sie eben hereingetreten waren, blickte von der
Thür ein großes dunkles Christusbild zu ihr nieder, die Züge kaum
kenntlich, ein schwarzer Fleck, umhüllt und umkleidet von
unendlichem Goldglanz. Sie starrte darauf hin, bis sie vor Thränen
nichts mehr sah. Rätsel hinter Gold —.
Aber leise und wohlthuend legte sich die Dämmerung dieser
Kirchenwände wie schützend um sie. Kaum glichen sie Wänden,
bedeckt mit alten nachgedunkelten Malereien wie reiche alte Stoffe,
sich niedrig wölbend und wellend, wie ein ungeheurer Mantel, der
sich in schweren weichen Falten um den Betenden legt, ihn sanft
bergend vor der Außenwelt —.
Sie hob beide Hände vor das Gesicht und beugte sich tief vor,
ohne ein Wort zu sprechen. Schweigend verharrte sie lange so.
Hier und da kamen von draußen Menschen vorüber, meistens
Leute aus dem Volk; leise auftretend mit ihrem groben Schuhwerk,
schritten sie tiefer hinein in das Schiff der Kirche, das in feierlicher
Dämmerung vor ihnen dalag, nur an wenigen Punkten schwach
erhellt von vereinzelten Wachskerzen, die daraus hervorblinkten.
Hugo Lanz stand neben Marianne, an ihre Bank gelehnt, und
blickte auf sie nieder. Er wußte nicht, was in ihr vorgehn mochte,
aber daß in dieser Stille etwas Erschütterndes in ihrer Seele zum
Austrag kam, das mußte er wohl fühlen — —. Und wenn er einst zu
ihr gekommen war im drängenden Verlangen, an ihrer warmen
Mütterlichkeit getrost und froh zu werden wie ein Kind, so wuchs
jetzt eine Sehnsucht in ihm empor, — groß, wie er sie nie gekannt
hatte, — stark zu werden und kraftvoll, ein Mann, um beschützen
und behüten zu dürfen —.
Er stand da und horchte stumm auf das Geläute der Glocken, —
auf den seltsam packenden Klang dieser russischen Glocken, die sich
weigern, sich mit ihren Klängen mitzuwiegen, und ehern feststehn,
daß der Klöppel in ihnen anschlägt wie ein weithin tönender
Befehl — —.
Da ließ Marianne die Hände von ihrem Gesicht sinken und erhob
sich ganz langsam. Hugo Lanz machte eine Bewegung zu ihr hin,
aber die Andacht in ihren Augen und in ihrer ganzen Haltung bannte
ihn. Es war wie eine unsichtbare Einsamkeit und Hoheit um sie, die
er nicht zu entweihen wagte. Und unwillkürlich trat er zur Seite.
Einen Augenblick lang stand Marianne da, sich besinnend, fast
schüchtern, mit einer sanften Neigung des Kopfes, die etwas
Rührendes für ihn hatte, etwas von unaussprechlicher Ergebung.
Aber auf ihren Zügen lag ein ruhiger Glanz, alle Angst war von ihnen
gewichen.
Sie machte eine Wendung, um aus dem Portal hinauszutreten,
ohne ihren Begleiter zu bemerken. In diesen Minuten hatte sie auch
ihn vergessen. Er schaute ihr nach, und unwiderleglich kam ihm das
Gefühl: — als ginge sie gar nicht allein — —.
Ein paar Schritte hinter ihr trat er hinaus auf den Platz.
Unten in der Stadt, die dem Kreml zu Füßen lag, blinkten eben die
ersten Lichter auf. Schon war es nicht mehr ganz hell. Weißlicher
Winternebel zog sich in der Ferne über die Ufer des Flusses. Fest um
den Kreml geschmiegt, standen die Häuser da, rot und blau und
grün an Dächern oder Mauerwerk, und erwarteten nach des Tages
Treiben das Dunkel, durch das das siegende Gold der zahllosen
Kuppeln hindurchschien wie eine ewige Leuchte, die nicht mit dem
Tage erlischt.
Ein unerhörtes Abendrot stand über Moskau. Und die Buntheit der
Farben ringsum nahm auch noch den schwächsten Abglanz davon,
nahm auch den leisesten Funken so innig auf, hielt sich ihm an der
Oberfläche aller Dinge als ein so williges Gefäß entgegen, daß es
fast wirkte wie ein Lobgesang, der emporstieg von der Erde zum
erglühenden Himmel. Eine Stimmung wie ein Ausgleich zwischen
Freude und Gebet lag über dem Ganzen. Die paar Wolken, die
inmitten der Bläue des Himmels zögernd dunkelten, zogen sich,
lichtdurchschossen, langsam zu breitschimmernden Goldbändern
auseinander — —.
Da ging ein flüchtiger Regenschauer nieder, warm und ganz kurz,
wie ein Thränensturz.
Hugo Lanz blieb stehn und schaute hinab, dorthin wo Mas feine
ruhige Gestalt im Abstieg zu den Anlagen sichtbar blieb.
Wie klein und unscheinbar verschwand sie dort zwischen den
Bäumen. Und ihm schien doch alles ringsum sie allein zu feiern und
zu umstrahlen —.
Denn in ihm arbeitete sich irgend ein Bild mit mächtiger Gewalt zu
künstlerischer Klarheit hindurch, — ein Bild, in dem er Ma vor sich
sah, — ein Bild, in dem ihr Glück lebte und ihr Vereinsamen, und ihr
Weh, und ihr Sieg, — ein Bild, in dem geheimnisvoll lebte, was in
diesem Augenblick in ihr selbst wohl nur in dunkeln Ahnungen
rang — —.
Und es kam ihm vor, als stünde er angesichts eines großen
Schauspiels, um deswillen man das Leben fürchten und lieben lernen
mag. Und das den Schauenden, dem es seine Heimlichkeit enthüllt,
zum Kinde werden lassen mag, und zum Manne, — und zum Dichter.
— Ganz benommen und wie sich selbst entrückt, blickte er hinab
von der Kremlhöhe in die Tiefe der Stadt.
So sah er Ma schweigend, still niedersteigen unter dem
verhallenden Geläute der Glocken, — einen von oben in die
Wohnungen der Menschen entsendeten guten Geist.
J. G. Cotta'sche Buchhandlung
Nachfolger G. m. b. H. in Stuttgart.

Die nachstehend verzeichneten Romane und Novellen sind auch


elegant in Leinwand gebunden zu beziehen.

Preis für den Einband 1 Mark.


A n d r e a s - S a l o m é , Lou, Ruth. Erzählung. 3. Auflage. Geheftet M. 3.50.
—"— Aus fremder Seele. Eine Spätherbstgeschichte.
2. Aufl. " M. 2.—
—"— Fenitschka. Eine Ausschweifung. Zwei
Erzählungen. " M. 2.50.
—"— Menschenkinder. Novellencyklus. " M. 3.50.
—"— Ma. Ein Porträt. " M. 2.50.
A n z e n g r u b e r , Ludw., Wolken und Sunn'schein.
2. Aufl. " M. 3.—
A r m i n i u s , Wilhelm, Der Weg zur Erkenntnis.
Roman. " M. 3.—
—"— Yorks Offiziere. Historischer Roman. " M. 3.50.
B o b e r t a g , Bianca, Moderne Jugend. Roman. " M. 4.—
B o u r g e t , Paul, Das gelobte Land. Roman. " M. 3.—
B o y - E d , Ida, Die Lampe der Psyche. Roman. 2. Aufl. " M. 4.—
—"— Um Helena. Roman. " M. 3.50.
B ü l o w , Frieda v., Kara. Roman. " M. 4.—
B u r c k h a r d , Max, Simon Thums. 2. Auflage. " M. 3.—
B u s s e , Carl, Die Schüler von Polajewo. Novellen. " M. 2.50.
E b n e r - E s c h e n b a c h , Marie v., Erzählungen.
3. Aufl. " M. 3.—
—"— Božena. Erzählung. 5. Auflage. " M. 3.—
—"— Margarete. 4. Auflage. " M. 2.—
— Moriz v., Hypnosis perennis. Ein Wunder des
heiligen
Sebastian. Zwei Wiener Geschichten. " M. 2.—
E c k s t e i n , Ernst, Nero. Roman. 6. Auflage. " M. 5.—
E r t l , Emil, Mistral. Novellen. " M. 3.—
F u l d a , L., Lebensfragmente. Zwei Novellen. 7. Auflage. " M. 2.—
H a u s h o f e r , Max, Planetenfeuer. Ein Zukunftsroman. " M. 3.50.
H e e r , J. C., An heiligen Wassern. Roman. 6. Auflage. " M. 3.50.
—"— Der König der Bernina. Roman. 9. Auflage. " M. 3.50.
H e i l b o r n , Ernst, Kleefeld. Roman. " M. 2.—
H e y s e , Paul, Neue Novellen. 7. Auflage. " M. 3.50.
—"— Marthas Briefe an Maria. 2. Auflage. " M. 1.—
H i l l e r n , Wilhelmine v., 's Reis am Weg. 2. Auflage. " M. 1.50.
—"— Ein alter Streit. Roman. 3. Auflage. " M. 3.—
H ö c k e r , Paul Oskar, Väterchen. Roman. " M. 3.—
H o p f e n , H., Der letzte Hieb. Eine Studentengeschichte.
3. Aufl. " M. 2.50.
J u n g h a n s , Sophie, Schwertlilie. Roman. 2. Auflage. " M. 4.—
K i r c h b a c h , Wolfgang, Miniaturen. Fünf Novellen. " M. 4.—
L a n g m a n n , Philipp, Verflogene Rufe. Novellen. " M. 2.50.
L i n d a u , Paul, Der Zug nach d. Westen. Roman.
9. Aufl. " M. 4.—
L o t i , Pierre, Japanische Herbsteindrücke. " M. 3.—
M a u t h n e r , Fritz, Hypatia. Roman. 2. Auflage. " M. 3.50.
M e y e r - F ö r s t e r , Wilhelm, Eldena. Roman. 2. Auflage. " M. 3.—
M u e l l e n b a c h , E. (E. Lenbach), Abseits. Erzählungen. " M. 3.—
—"— Vom heißen Stein. Roman. " M. 3.—
Pe t r i , Julius, Pater peccavi! Roman. " M. 3.—
P r e l , Karl du, Das Kreuz am Ferner. Roman. 2. Aufl. " M. 5.—
P r o e l ß , Johannes, Bilderstürmer! Roman. 2. Auflage. " M. 4.—
R i e h l , W. H., Aus der Ecke. Sieben Novellen. 4. Auflage. " M. 4.—
—"— Neues Novellenbuch. 3. Aufl. (6. Abdruck.) " M. 4.—
S a i t s c h i c k , Robert, Aus der Tiefe. Ein Lebensbuch. " M. 2.—
S c h u n s u i , Tamenaga, Treu bis in den Tod. Hist.
Roman. " M. 3.—
S e i d e l , Heinrich, Leberecht Hühnchen.
Gesamtausgabe. " M. 4.—
S t e g e m a n n , Hermann, Stille Wasser. Roman. " M. 3.—
S t r a t z , Rudolph, Der weiße Tod. Roman. 5. Auflage. " M. 3.—
—"— Buch der Liebe. Sechs Novellen. 2. Auflage. " M. 2.50.
—"— Der arme Konrad. Roman. 3. Auflage. " M. 3.—
—"— Die letzte Wahl. Roman. 3. Auflage. " M. 3.50.
—"— Montblanc. Roman. 5. Auflage. " M. 3.—
—"— Die ewige Burg. Roman. 3. Auflage. " M. 3.—
—"— Die thörichte Jungfrau. Roman. 5. Auflage. " M. 3.50.
S u d e r m a n n , Herm., Frau Sorge. Roman. 57. Auflage. " M. 3.50.
—"— Geschwister. Zwei Novellen. 22. Auflage. " M. 3.50.
—"— Der Katzensteg. Roman. 44. Auflage. " M. 3.50.
—"— Im Zwielicht. Zwanglose Geschichten. 26. Auflage. " M. 2.—
—"— Jolanthes Hochzeit. Erzählung. 23. Auflage. " M. 2.—
—"— Es war. Roman. 30. Auflage. " M. 5.—
Te l m a n n , Konrad, Trinacria. Sizilische Geschichten. " M. 4.—
Vo ß , Richard, Römische Dorfgeschichten. 4. Auflage. " M. 3.—
We r e s c h a g i n , W. W., Der Kriegskorrespondent. " M. 2.—
W i d m a n n , J. V., Touristennovellen. " M. 4.—
W i l b r a n d , Adolf, Fridolins heimliche Ehe. 3. Aufl. " M. 2.50.
—"— Meister Amor. Roman. 2. Auflage. " M. 3.50.
—"— Novellen aus der Heimat. 2. Auflage. " M. 3.50.
—"— Hermann Isinger. Roman. 5. Auflage. " M. 4.—
—"— Der Dornenweg. Roman. 4. Auflage. " M. 3.50.
—"— Die Osterinsel. Roman. 3. Auflage. " M. 4.—
—"— Die Rothenburger. Roman. 5. Auflage. " M. 3.—
—"— Vater und Sohn und andere Geschichten. 2. Auflage. " M. 3.—
—"— Hildegard Mahlmann. Roman. 3. Auflage. " M. 3.50.
—"— Schleichendes Gift. Roman. 3. Auflage. " M. 3.—
—"— Die glückliche Frau. Roman. 4. Auflage. " M. 3.—
—"— Vater Robinson. Roman. 3. Auflage. " M. 3.—
—"— Der Sänger. Roman. 4. Auflage. " M. 4.—
—"— Erika. Das Kind. Erzählungen. 3. Auflage. " M. 3.50.
—"— Feuerblumen. Roman. 3. Auflage. " M. 3.—
—"— Franz. Roman. 3. Auflage. " M. 3.50.
—"— Das lebende Bild und andere Geschichten.
3. Auflage. " M. 3.—
W i l d e n b r u c h , E. v., Schwester-Seele. Roman.
11. Aufl. " M. 4.—
Wo r m s , Carl, Du bist mein. Zeitroman. " M. 4.—
—"— Thoms friert. Roman. " M. 4.—
Hinweise zur Transkription

Das Originalbuch ist in Frakturschrift gedruckt.


Darstellung abweichender Schriftarten: g e s p e r r t , Antiqua.
Verlagswerbung wurde vom Buchanfang an das Buchende
verschoben.
Der Text des Originalbuches wurde grundsätzlich beibehalten, mit
folgenden Ausnahmen,
Seite 23:
"nichs" geändert in "nichts"
(Nun, das macht nichts.)
Seite 49:
"leiebkosende" geändert in "liebkosende"
(als seien es ebensoviel liebkosende Verheißungen)
Seite 63:
"»" eingefügt
(»die schönsten Lieder und die schönsten Sagen)
Seite 109:
"auch" geändert in "nach"
(in die Hand nehmen und nach deinem stärkeren Willen
prägen)
Seite 112:
"«" eingefügt
(Sie ist aber nicht krank geworden.«)
Seite 160:
"halbmäd henhafte" geändert in "halbmädchenhafte"
(Dabei hatte sie irgend eine halbmädchenhafte Kopfhaltung)
Seite 168:
"Das" geändert in "das"
(»Nein, — das heißt: es wäre ja wunderschön)
Seite 179:
"." eingefügt
(um alle Kraft aufzuzehren —.)
Seite 185:
"«" hinter "helfen?" entfernt
(Was konnt es denn helfen?)
*** END OF THE PROJECT GUTENBERG EBOOK MA: EIN PORTRÄT
***

Updated editions will replace the previous one—the old editions will
be renamed.

Creating the works from print editions not protected by U.S.


copyright law means that no one owns a United States copyright in
these works, so the Foundation (and you!) can copy and distribute it
in the United States without permission and without paying
copyright royalties. Special rules, set forth in the General Terms of
Use part of this license, apply to copying and distributing Project
Gutenberg™ electronic works to protect the PROJECT GUTENBERG™
concept and trademark. Project Gutenberg is a registered trademark,
and may not be used if you charge for an eBook, except by following
the terms of the trademark license, including paying royalties for use
of the Project Gutenberg trademark. If you do not charge anything
for copies of this eBook, complying with the trademark license is
very easy. You may use this eBook for nearly any purpose such as
creation of derivative works, reports, performances and research.
Project Gutenberg eBooks may be modified and printed and given
away—you may do practically ANYTHING in the United States with
eBooks not protected by U.S. copyright law. Redistribution is subject
to the trademark license, especially commercial redistribution.

START: FULL LICENSE


THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the free


distribution of electronic works, by using or distributing this work (or
any other work associated in any way with the phrase “Project
Gutenberg”), you agree to comply with all the terms of the Full
Project Gutenberg™ License available with this file or online at
www.gutenberg.org/license.

Section 1. General Terms of Use and


Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand, agree
to and accept all the terms of this license and intellectual property
(trademark/copyright) agreement. If you do not agree to abide by all
the terms of this agreement, you must cease using and return or
destroy all copies of Project Gutenberg™ electronic works in your
possession. If you paid a fee for obtaining a copy of or access to a
Project Gutenberg™ electronic work and you do not agree to be
bound by the terms of this agreement, you may obtain a refund
from the person or entity to whom you paid the fee as set forth in
paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only be


used on or associated in any way with an electronic work by people
who agree to be bound by the terms of this agreement. There are a
few things that you can do with most Project Gutenberg™ electronic
works even without complying with the full terms of this agreement.
See paragraph 1.C below. There are a lot of things you can do with
Project Gutenberg™ electronic works if you follow the terms of this
agreement and help preserve free future access to Project
Gutenberg™ electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright law
in the United States and you are located in the United States, we do
not claim a right to prevent you from copying, distributing,
performing, displaying or creating derivative works based on the
work as long as all references to Project Gutenberg are removed. Of
course, we hope that you will support the Project Gutenberg™
mission of promoting free access to electronic works by freely
sharing Project Gutenberg™ works in compliance with the terms of
this agreement for keeping the Project Gutenberg™ name associated
with the work. You can easily comply with the terms of this
agreement by keeping this work in the same format with its attached
full Project Gutenberg™ License when you share it without charge
with others.

1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside the
United States, check the laws of your country in addition to the
terms of this agreement before downloading, copying, displaying,
performing, distributing or creating derivative works based on this
work or any other Project Gutenberg™ work. The Foundation makes
no representations concerning the copyright status of any work in
any country other than the United States.

1.E. Unless you have removed all references to Project Gutenberg:

1.E.1. The following sentence, with active links to, or other


immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project Gutenberg™
work (any work on which the phrase “Project Gutenberg” appears,
or with which the phrase “Project Gutenberg” is associated) is
accessed, displayed, performed, viewed, copied or distributed:
This eBook is for the use of anyone anywhere in the United
States and most other parts of the world at no cost and with
almost no restrictions whatsoever. You may copy it, give it away
or re-use it under the terms of the Project Gutenberg License
included with this eBook or online at www.gutenberg.org. If you
are not located in the United States, you will have to check the
laws of the country where you are located before using this
eBook.

1.E.2. If an individual Project Gutenberg™ electronic work is derived


from texts not protected by U.S. copyright law (does not contain a
notice indicating that it is posted with permission of the copyright
holder), the work can be copied and distributed to anyone in the
United States without paying any fees or charges. If you are
redistributing or providing access to a work with the phrase “Project
Gutenberg” associated with or appearing on the work, you must
comply either with the requirements of paragraphs 1.E.1 through
1.E.7 or obtain permission for the use of the work and the Project
Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is posted


with the permission of the copyright holder, your use and distribution
must comply with both paragraphs 1.E.1 through 1.E.7 and any
additional terms imposed by the copyright holder. Additional terms
will be linked to the Project Gutenberg™ License for all works posted
with the permission of the copyright holder found at the beginning
of this work.

1.E.4. Do not unlink or detach or remove the full Project


Gutenberg™ License terms from this work, or any files containing a
part of this work or any other work associated with Project
Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute this


electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1

You might also like