回答編集履歴

1

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

2020/05/24 04:09

投稿

kakajika
kakajika

スコア3131

test CHANGED
@@ -37,3 +37,107 @@
37
37
  viewModel.buttonImage.drive(button.rx.image())
38
38
 
39
39
  ```
40
+
41
+
42
+
43
+ ---
44
+
45
+
46
+
47
+ **追記**
48
+
49
+
50
+
51
+ コードを載せていただいていないので推測になりますが、ご質問の状況はMVVMの設計思想から外れた実装をしているために起きているものだと思います。基本的に、MVVMではViewを更新する際にはViewModelを介して行います。ViewとViewModelのやり取りは
52
+
53
+
54
+
55
+ - View => ViewModel - UIに関するイベントをViewModelに伝える
56
+
57
+ - ViewModel => View - UIの状態を表すデータを更新し、Viewに伝える
58
+
59
+
60
+
61
+ という2通りのものであるべきです。
62
+
63
+
64
+
65
+ おそらく、質問者さんのコードだとユーザーが画像を選択した際にUIButtonにそのまま画像を設定しているのだと思いますが、それだとViewがViewModelを介さずに勝手にUIを更新していることになります。これではMVVMの原則に反してしまうので、次のようにViewModelを介するように変更してみてください。これでViewModelとViewの状態は同じに保たれるため、UIButtonのimageをViewModelに伝える方法を考える必要は無くなります。
66
+
67
+
68
+
69
+ 1. View: 画像を選択したイベントをViewModelに伝える
70
+
71
+ 2. ViewModel: UIButtonの画像を表すデータを更新し、Viewに伝える
72
+
73
+
74
+
75
+ 以下、実装イメージを載せておきます。
76
+
77
+
78
+
79
+ - View側
80
+
81
+
82
+
83
+ ```swift
84
+
85
+ viewModel.buttonImage.drive(button.rx.image())
86
+
87
+ registerButton.rx.tap.bind(to: viewModel.onRegisterButtonClick)
88
+
89
+
90
+
91
+ // カメラロール等で画像を選択した時のコールバック(適当に読み替えてください)
92
+
93
+ func imageDidSelect(image: UIImage) {
94
+
95
+ viewModel.onImageSelected.accept(image)
96
+
97
+ }
98
+
99
+ ```
100
+
101
+
102
+
103
+ - ViewModel側
104
+
105
+
106
+
107
+ ```swift
108
+
109
+ // Output: ViewModel => View
110
+
111
+ let buttonImage: Driver<UIImage>
112
+
113
+
114
+
115
+ // Input: View => ViewModel
116
+
117
+ let onImageSelected = PublishRelay<UIImage>()
118
+
119
+ let onRegisterButtonClick = PublishRelay<Void>()
120
+
121
+
122
+
123
+ init(...) {
124
+
125
+ self.buttonImage = self.onImageSelected.asDriver(...)
126
+
127
+
128
+
129
+ self.onRegisterButtonClick
130
+
131
+ .withLatestFrom(self.buttonImage)
132
+
133
+ .subscribe(onNext: { selectedImage in
134
+
135
+ // 画像をアップロードする処理...
136
+
137
+ })
138
+
139
+ .disposed(by: ...)
140
+
141
+ }
142
+
143
+ ```