Home > Enterprise >  Combine assign(to:) with a @Published var
Combine assign(to:) with a @Published var

Time:06-16

I have an enum in my project:

enum Remote<Content> {
  case .notAsked
  case .loading
  case .loaded(Content)
  case .failed(Error)
}

I then have a class:

class MyViewModel: ObservableObject {
  @Published var content: Remote<ContentStruct> = .notAsked

  func fetchContent() {
    content = .loading

    service.fetchContent()
      .receive(on: queue)
      .map(Remote<ContentStruct>.loaded)
      .catch { error in Just(.failed(error)) }
      .assign(to: &self.content)
  }
}

But this complains to me that:

Cannot convert value of type 'Remote<ContentStruct>' to expected argument type 'Published<Remote<ContentStruct>>.Publisher'

I can change it to use this:

func fetchContent() {
  content = .loading

  service.fetchContent()
    .receive(on: queue)
    .map(Remote<ContentStruct>.loaded)
    .catch { error in Just(.failed(error)) }
    .assign(to: \.content, on: self)
    .store(in: &cancellables)
}

And this works and assigns the value correctly. But I don't understand why I can't use the .assign(to: keyPath) function on there?

Do I need to do something different? We've only recently updated to support a minimum of iOS14 and so not been using assign(to: before due to memory leaks and now I'm just not sure how this is working.

Thanks

CodePudding user response:

assign(to:) requires a Published.Publisher as its input. So you need to pass the publisher from the Publisher property wrapper, which you can access using the $ prefix.

.assign(to: &$content)
  • Related