質問するログイン新規登録

回答編集履歴

1

MVVMらしい設計について追記

2020/05/24 04:09

投稿

kakajika
kakajika

スコア3133

answer CHANGED
@@ -17,4 +17,56 @@
17
17
 
18
18
  ```swift
19
19
  viewModel.buttonImage.drive(button.rx.image())
20
+ ```
21
+
22
+ ---
23
+
24
+ **追記**
25
+
26
+ コードを載せていただいていないので推測になりますが、ご質問の状況はMVVMの設計思想から外れた実装をしているために起きているものだと思います。基本的に、MVVMではViewを更新する際にはViewModelを介して行います。ViewとViewModelのやり取りは
27
+
28
+ - View => ViewModel - UIに関するイベントをViewModelに伝える
29
+ - ViewModel => View - UIの状態を表すデータを更新し、Viewに伝える
30
+
31
+ という2通りのものであるべきです。
32
+
33
+ おそらく、質問者さんのコードだとユーザーが画像を選択した際にUIButtonにそのまま画像を設定しているのだと思いますが、それだとViewがViewModelを介さずに勝手にUIを更新していることになります。これではMVVMの原則に反してしまうので、次のようにViewModelを介するように変更してみてください。これでViewModelとViewの状態は同じに保たれるため、UIButtonのimageをViewModelに伝える方法を考える必要は無くなります。
34
+
35
+ 1. View: 画像を選択したイベントをViewModelに伝える
36
+ 2. ViewModel: UIButtonの画像を表すデータを更新し、Viewに伝える
37
+
38
+ 以下、実装イメージを載せておきます。
39
+
40
+ - View側
41
+
42
+ ```swift
43
+ viewModel.buttonImage.drive(button.rx.image())
44
+ registerButton.rx.tap.bind(to: viewModel.onRegisterButtonClick)
45
+
46
+ // カメラロール等で画像を選択した時のコールバック(適当に読み替えてください)
47
+ func imageDidSelect(image: UIImage) {
48
+ viewModel.onImageSelected.accept(image)
49
+ }
50
+ ```
51
+
52
+ - ViewModel側
53
+
54
+ ```swift
55
+ // Output: ViewModel => View
56
+ let buttonImage: Driver<UIImage>
57
+
58
+ // Input: View => ViewModel
59
+ let onImageSelected = PublishRelay<UIImage>()
60
+ let onRegisterButtonClick = PublishRelay<Void>()
61
+
62
+ init(...) {
63
+ self.buttonImage = self.onImageSelected.asDriver(...)
64
+
65
+ self.onRegisterButtonClick
66
+ .withLatestFrom(self.buttonImage)
67
+ .subscribe(onNext: { selectedImage in
68
+ // 画像をアップロードする処理...
69
+ })
70
+ .disposed(by: ...)
71
+ }
20
72
  ```