Skip to content

Instantly share code, notes, and snippets.

@mbrandonw
Last active June 23, 2020 13:57
Show Gist options
  • Select an option

  • Save mbrandonw/2f8290f10c3da8400852ac94c8a90eec to your computer and use it in GitHub Desktop.

Select an option

Save mbrandonw/2f8290f10c3da8400852ac94c8a90eec to your computer and use it in GitHub Desktop.

FB7755967

@Published property emits differently in iOS 14 versus iOS 13

The following test fails on iOS 14 but passes in iOS 13:

func testCombineBug() {
  class Store {
    var cancellable: AnyCancellable?
    @Published var count: Int
    init(count: Int = 0) { self.count = count }

    func scope() -> AnyPublisher<Store, Never> {
      self.$count.map { count in
        let child = Store(count: count)
        child.cancellable = self.$count.sink { [weak child] count in
          child?.count = count
        }
        return child

      }
      .eraseToAnyPublisher()
    }
  }

  let parentStore = Store()
  var outputs: [Int] = []

  parentStore.scope()
    .sink { childStore in
      childStore.$count
        .sink { outputs.append($0) }
        .store(in: &self.cancellables)
    }
    .store(in: &self.cancellables)

  XCTAssertEqual(outputs, [0])
  parentStore.count = 1
  XCTAssertEqual(outputs, [0, 1])
  parentStore.count = 2
  XCTAssertEqual(outputs, [0, 1, 2])
}

If I swap out the @Published property for a CurrentValueSubject the test will pass again.

To reproduce open the sample project I have attached and run tests for iOS.

This may seem like a strange way to structure some publishers, but it’s important for our library that uses this style in order to drive UIKit navigation from state changes: https://github.com/pointfreeco/swift-composable-architecture/blob/c9c1a9a50040408c436e496bac35007add327186/Sources/ComposableArchitecture/Store.swift#L85-L123

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment