Search code examples
swiftswiftuicombine

Need keypath syntax for use in assign(to:_) in SwiftUI


I'm new to SwiftUI and have been following along with @peter-friese's example SwiftUI/Firebase app.

My example app works perfectly, but am now trying to modify slightly but am unable to get the correct keypath syntax of in the assign/map in order to set a property.

Relevantly (and slightly simplified), there is a struct for the data model:

struct Task: Codable, Identifiable {
  var title: String
  var status: Bool
  var flag: Bool
}

and a class for a view model:

class TaskCellViewModel {
  @Published var task: Task
  var iconName:String = "" 
}

In this tutorial a map/assign is used within the TaskCellViewModel to set the value of the iconName property in the instance of the TaskCellViewModel as follows:

private var cancellables = Set<AnyCancellable>()

init(task: Task) {
    self.task = task
$task
   .map { task in
            task.status ? "checkmark.circle.fill" : "circle"
        }
   .assign(to: \.iconName, on: self)
   .store(in: &cancellables)
}

This works for setting the iconName. What is the correct syntax to set the flag property on the Task itself?

I have tried various combinations but none work, including:

.assign(to .\Task.task.flag, on: self)
.assign(to .\task.flag, on: self)
.assign(to .\Task.task.flag, on: TaskCellViewModel)

Using Task.task.flag it fails at runtime with EXC_BAD_ACCESS error or a type conversion compile error:

Cannot convert value of type AnswerRowViewModel.Type to expected argument type AnswerRowViewModel.

PS given I'm learning and trying to follow along with the tutorials, I'm hoping for a answer to the assign/map question - as opposed to a workaround/alternative.


Solution

  • Use sink instead

    .sink { [weak self] flag in
       self?.task.flag = flag
    }