LoginSignup
0
1

More than 3 years have passed since last update.

@Published を監視する

Posted at
struct Content: Hashable {
    let name: String
}

extension Content: Identifiable {
    var id: Content { self }
}

class ContentViewModel: ObservableObject {
    @Published var contents: [Content] = [.init(name: "piyo")]
}

上記のようなViewModelを実装した際にcontentsの更新を監視したい場合がある

解決策

viewModel.$contents
    .sink { contents in
        print(contents)
    }

もしくは

viewModel.objectWillChange
    .sink {
        print("willChange")
    }

これで値を購読することができる

注意するべきポイントとして、どちらも値更新前に呼ばれるのでsinkが呼ばれたタイミングでは値は更新されていない。
プロパティを直接購読する場合は更新後の値が取れるが、
objectWillChangeを購読する場合はObservableObjectに生えているプロパティそれぞれの更新タイミングを取得することができるが更新後の値は取得できない

余談

ちなみに、ViewのinitializerなどでViewModelにあるPublishedObjectの更新前の値を参照したい場合に直接クロージャーで扱おうとするとEscaping closure captures mutating 'self' parameterと出てしまうので、値をコピーする必要がある。
コピーをするだけなのでクロージャー内で値を書き換えてもViewの保持するViewModelには何も影響は出ない。

viewModel.$contents
    .sink { [previousContents = viewModel.contents] _ in
        print(previousContents)
    }
typealias DisposeBag = Set<AnyCancellable>

struct ContentView: View {
    @ObservedObject var viewModel = ContentViewModel()
    private var disposeBag = DisposeBag()
    var body: some View {
        NavigationView {
            List {
                ForEach(viewModel.contents) { content in
                    NavigationLink(
                        destination: Text(content.name),
                        label: {
                            Text(content.name)
                        })
                }
            }
        }
    }
    init() {
        viewModel.$contents
            .sink { [previousContents = viewModel.contents] contents in
                print(contents)
                print(previousContents)
            }
            .store(in: &disposeBag)
    }
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1