Errata for Combine: Asynchronous Programming with Swift 1st Edition (v1.0.3)

That fixed it for me! Thanks for the quick response. I was able to ‘print’ and see the timer canceled but I put all of my effort into the PostedBy helper. Never even thought about changing the order in the main view. I’m going to need to read that SwiftUI book now so I understand what’s behind that curtain. :grinning:

Minor editorial fixes:

Chapter 3 - Collecting Values - collect() - last sentence first paragraph:

“To help understand how this and all other operators you’ll learn about in this book, you’ll use marble diagrams.”

Need to either remove “how” or add “work” or (forgive me) “operate” after “book”.


Chapter 3 - Flattening Publishers - last paragraph, last sentence:

"So, before wrapping up this chapter, you’ll learn a couple more useful operating for doing the ol’ switcheroo.”

“operating” should be “operators”

A few other minor editorial fixes:

Chapter 15 - near the end, as keywords and SettingsView are wrapping up:

Remember, adding the keyword to the list here will update the settings model object and in turn, will update the reader view model and refresh RenderView as well.

RenderView should be ReaderView. Thanks!


Chapter 18 - near the end, when adding subscriptions:

let subscription1 = publisher.sink(
  receiveCompletion: {
    print("subscription2 completed: \($0)", to: &logger)
  },
  receiveValue: {
    print("subscription2 received \($0)", to: &logger)
  }
)

subscription1 is printing descriptions for “subscription2” (subscription2 is printing the same)


Chapter 20 - Last sentence of the Note before the Setting Goals section:

However, if the preview rendering fails, of if you’re still running macOS Mojave, you can also build and run the app to a simulator to check out your progress.

“of” should be “or”

I have a question on pg. 204 regarding the handling of dismissing the alert automatically when the currently-presented view controller is dismissed.

 extension UIViewController {
    func alert(title: String, text: String?) -> AnyPublisher<Void, Never> {
        let alertVC = UIAlertController(title: title,
                                        message: text,
                                        preferredStyle: .alert)
        
        return Future { resolve in
            alertVC.addAction(UIAlertAction(title: "Close", style: .default) { _ in
                resolve(.success(()))
            })
            
            self.present(alertVC, animated: true, completion: nil)
        }
        .handleEvents(receiveCancel: {
            self.dismiss(animated: true)
        })
        .eraseToAnyPublisher()
    }
}

Assuming in the currently-presented view controller, we are storing the alert subscription when we present the alert and subscribe to the Future returned.

Pg. 204 says:

This code handles the case when you tie the alert subscription to the currently-presented view controller and that controller gets dismissed itself. This will cancel the alert subscription and dismiss that alert as well.

However, it seems like the receiveCancel closure is strongly referencing/capturing self, so in the case that the controller gets popped or dismissed itself, the controller (and its alert subscription) still won’t get de-init’ed because the receiveCancel closure has a reference of it.

Changing the receiveCancel to capture weak self and self?.dismiss(...) wouldn’t help either, because by the time receiveCancel is invoked due to the VC getting de-inited, the weak self is already nil’ed and dismiss would not get called.

Any idea on how to properly handle this?

Minor typo at Chapter 2 page 41: log output “Example of: Publisher” but that time it should be “Example of: Subscriber” as code piece already:

example(of: "Subscriber") {

Chapter 2 page 45: tell us to add code for subscription cancellation, but that piece of code was already added previously (page 41)

Chapter 4 page 107:

… ignores any values emitted by the publisher until the first time that predicate is met. As soon as the predicate is met, values begin to flow through the operator.

I believe this should be changed to:

… ignores any values emitted by the publisher until the first time that predicate is not met. As soon as the predicate is not met, values begin to flow through the operator.

With this in mind, the text on the following page should be updated. It is treating the predicate ($0 % 5 != 0) as asking “is this divisible by 5?” when the predicate is actually asking “is this not divisible by 5?”.