0

次のテスト コードの何が問題になっていますか? フィールドに文字を入力すると、didSet が再帰ループに入ります。inout + & が削除された場合、コードは期待どおりに機能し、キーストロークごとに didSet がトリガーされます。同様に、@Published を削除しても、inout と & をそのままにしておくと、didSet の再帰は発生しません。

なぜ私はこれをやろうとしているのですか?私はフォーム フィールド タイプ (4 文字の 16 進数フィールド) を持っています。これは、基本構造に再エンコードされる共通の処理を必要とします。したがって、その意図は、ModelView ゾーンで各 var が設定された後にトリガーされる関数にすべての共通コードを抽象化することです。このコードは、問題を再現するための最小限の例です。

@published変数のアドレスを取得するだけで、関連付けられた didSet がトリガーされるようです。これを解釈すると、inout を使用すると、変更が行われなくても常にターゲット var が書き換えられるということになります。

class A: ObservableObject
{
  @Published var publishedVar = "abc" {
    didSet {
      print("didSet Triggered")
      doNothing(commonText: &publishedVar)
    }
  }
  
  private func doNothing(commonText: inout String)
  {
  }

}

struct ContentView: View {
  @ObservedObject var a = A()
    var body: some View {
      TextField("dummy", text: $a.publishedVar)
    }
}

関連する場合、これは Catlina を Mac アプリ (IOS やエミュレーターではなく) として実行している Mac で実行されています。Xcode バージョン 12.4 (12D4e)

OK、シンクでの読み取りを試み、アドバイスに従おうとしました (以下のクラス A を更新) が、doNothing 関数内で再帰的であることがわかりました。基本的なものが欠けているようです 8-(

class A: ObservableObject
{
  var cancellable: AnyCancellable?
  @Published var publishedVar: String = "def"
  
  private func doNothing(commonText: inout String)
  {
    print("In doNothing \(commonText)")
  }

  init()
  {
    cancellable = $publishedVar.sink { value in
      self.doNothing(commonText: &self.publishedVar)
      print("saw sink \(value)")
    }
  }
}
4

1 に答える 1