title: Dealing with Swift 5 Exclusivity Enforcement when using Combine
body: <p>Swift 5, the "Exclusive Access to Memory" enforcement is now on by default for release builds as mentioned in this Swift.org blog post: </p>
  
  <p><a href="https://swift.org/blog/swift-5-exclusivity/" rel="nofollow noreferrer">Swift 5 Exclusivity Enforcement</a></p>
  
  <p>I understand the reasoning behind this feature, but with the new <code>Combine</code> framework I feel as if some very normal design patterns are now going to break and I'm curious how best to work around them. </p>
  
  <p>With <code>Combine</code> it's natural for parts of your code to react to changes in a model such that they might need to read from the very property that the model has just changed. But they can no longer do that because it will trigger a memory exception as you attempt to read a value that is currently being set. </p>
  
  <p>Consider the following example: </p>
  
  <pre><code>struct PasswordProposal {
    let passwordPublisher = CurrentValueSubject&lt;String, Never&gt;("1234")
    let confirmPasswordPublisher = CurrentValueSubject&lt;String, Never&gt;("1234")
  
    var password:String {
      get { passwordPublisher.value }
      set { passwordPublisher.value = newValue }
    }
  
    var confirmPassword:String {
      get { confirmPasswordPublisher.value }
      set { confirmPasswordPublisher.value = newValue }
    }
  
    var isPasswordValid:Bool {
      password == confirmPassword &amp;&amp; !password.isEmpty
    }
  }
  
  class Coordinator {
    var proposal:PasswordProposal
    var subscription:Cancellable?
  
    init() {
      self.proposal = PasswordProposal()
      self.subscription = self.proposal.passwordPublisher.sink { [weak self] _ in
        print(self?.proposal.isPasswordValid ?? "")
      }
    }
  
    // Simulate changing the password to trigger the publisher.
    func changePassword() {
      proposal.password = "7890"
    }
  }
  
  // --------------------------------
  
  var vc = Coordinator()
  vc.changePassword()
  </code></pre>
  
  <p>As soon as <code>changePassword()</code> is called, the mutual exclusivity enforcement will throw an exception because the property <code>password</code> will attempt to be read from while it's currently being written to. </p>
  
  <p>Note that if you change this example to use a separate backing storage property instead of the <code>CurrentValueSubject</code> it causes the same exception. </p>
  
  <p>However, if you change <code>PasswordProposal</code> from being a <code>struct</code> to a <code>class</code>, then the exception is no longer thrown. </p>
  
  <p>When I consider how I might use <code>Combine</code> in an existing codebase, as well as in <code>SwiftUI</code>, I see this type of pattern coming up in a lot of places. In the old delegate model, it's quite common for a delegate to query the sending object from within a delegate callback. In Swift 5, I now have to be very careful that none of those callbacks potentially read from the property that initiated the notification. </p>
  
  <p>Have others come across this and, if so, how have you addressed it? Apple has routinely suggested that we should be using <code>structs</code> where it makes sense but perhaps an object that has published properties is one of those areas where it doesn't? </p>