title: How to connect published properties of model and viewmodel in Swift?
body: <p>Let's assume a model, which implements the protocol <code>ObservableObject</code> and has got a <code>@Published</code> property <code>name</code>. </p>
  
  <pre class="lang-swift prettyprint-override"><code>// MARK: Model
  class ContentSinglePropertyModel: ObservableObject {
      @Published public var name: String
  }
  </code></pre>
  
  <p>Now, I would like to display that name in a view and update the view, whenever <code>name</code> in the model changes. Additionally, I would like to use the Model-View-ViewModel (MVVM) pattern to achieve this goal. </p>
  
  <pre class="lang-swift prettyprint-override"><code>// MARK: ViewModel
  final class ContentSinglePropertyViewModel: ObservableObject {
      private let model: ContentSinglePropertyModel
  
      @Published var name: String = ""
  
      init() {
          self.model = ContentSinglePropertyModel()
      }
  }
  
  // MARK: View
  struct ContentSinglePropertyView: View {
      @ObservedObject var viewModel: ContentSinglePropertyViewModel
  
      var body: some View {
          Text(self.viewModel.name)
      }
  }
  </code></pre>
  
  <p>Since I don't like the idea to make the model or it's properties public within the viewmodel, one option is to wrap the model's property <code>name</code> in the viewmodel. <strong>My question is</strong>: How to connect the <code>name</code> of the model and the viewmodel in the most idiomatic way?</p>
  
  <p>I've came up with the solution to update the viewmodel's property through the use of Combine's <a href="https://developer.apple.com/documentation/combine/currentvaluesubject/3235789-assign" rel="noreferrer">assign</a> method:</p>
  
  <pre class="lang-swift prettyprint-override"><code>self.model.$name.assign(to: \.name, on: self).store(in: &amp;self.cancellables)
  </code></pre>
  
  <p>Is there a better solution?</p>
  
  <p>My working example:</p>
  
  <pre class="lang-swift prettyprint-override"><code>import SwiftUI
  import Combine
  
  // MARK: Model
  class ContentSinglePropertyModel: ObservableObject {
      @Published public var name: String
  
      init() {
          self.name = "Initial value"
      }
  
      func doSomething() {
          self.name = "Changed value"
      }
  }
  
  // MARK: ViewModel
  final class ContentSinglePropertyViewModel: ObservableObject {
      private let model: ContentSinglePropertyModel
      private var cancellables: Set&lt;AnyCancellable&gt; = []
  
      @Published var name: String = ""
  
      init() {
          self.model = ContentSinglePropertyModel()
  
          // glue Model and ViewModel
          self.model.$name.assign(to: \.name, on: self).store(in: &amp;self.cancellables)
      }
  
      func doSomething() {
          self.model.doSomething()
      }
  }
  
  // MARK: View
  struct ContentSinglePropertyView: View {
      @ObservedObject var viewModel: ContentSinglePropertyViewModel
  
      var body: some View {
          VStack {
              Text(self.viewModel.name)
  
              Button("Do something!", action: {
                  self.viewModel.doSomething()
              })
          }
      }
  }
  
  struct ContentSinglePropertyView_Previews: PreviewProvider {
      static var previews: some View {
          ContentSinglePropertyView(viewModel: .init())
      }
  }
  </code></pre>