質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

解決済

【SwiftUI】MVVMにおける値の連携方法(@Observed Objectなど)

ishiishiyay
ishiishiyay

総合スコア33

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

1回答

0評価

1クリップ

789閲覧

投稿2021/12/10 06:07

ViewModelでユーザー情報を取得するAPIを呼び、Modelに格納し、Viewに連携してあげたいです。
1つ目のやり方は成功したものの、コードを綺麗にするために2つ目のやり方を試したら失敗しました。
ご助言いただけますと幸いです。(MVVMアーキテクチャにおいて何かタブーなことをやっているのかもしれません。。)
何卒よろしくお願いいたします。

成功したコード

ViewModel

class AuthViewModel: ObservableObject { @Published var userMe: User? //UserはユーザーIDや名前など諸々の情報が入るModelのStructです。 init() {//アプリが開かれた瞬間にinitされる fetchUserMe() } func fetchUserMe() { //API通信 中略 self.userMe = try JSONDecoder().decode(User.self, from: data) } }

View

//このViewは、NavigationLinkで遷移する先となる子Viewです。親Viewは省略させていただきます。 struct ProfileHeaderView: View { @EnvironmentObject var viewModel: AuthViewModel var body: some View { HStack { Text( viewModel.userMe?.usersName ?? "nil") } }

View

@main struct FriendQA_SwiftUIApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView().environmentObject(AuthViewModel.shared) } } }

エラーになったコード

上記でうまくいくものの、AuthViewModelには既にたくさんの関数を書いてしまってごちゃごちゃしているので、
fetchUserMe関数を違うView Modelに移したいと思い、下記のコードに変えましたが、うまくいきませんでした。

ViewModel

class AuthViewModel: ObservableObject { @ObservedObject var fetchUsersViewModel = FetchUsersViewModel() init() { //アプリが開かれた瞬間にinitされる fetchUsersViewModel.fetchUserMe() } }

ViewModel

class FetchUsersViewModel: ObservableObject { @Published var userMe: User? func fetchUserMe() { //API通信 中略 self.userMe = try JSONDecoder().decode(User.self, from: data) print(self.userMe) //ちゃんと中身も出力される } }

View

struct ProfileHeaderView: View { @ObservedObject var fetchUsersViewModel = FetchUsersViewModel() var body: some View { HStack { Text(fetchUsersViewModel.userMe?.usersName ?? "nil") //nilになってしまう Text($fetchUsersViewModel.userMe.wrappedValue?.usersName ?? "nil") //nilになってしまう } }

最後まで読んでいただきありがとうございます。お手数ですが、お力添えいただけますと幸いです。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

hoshi-takanori

2021/12/10 06:49

同じクラスの異なるインスタンスを作ってるからでは。
ishiishiyay

2021/12/10 07:06

Hoshi-takanoriさん、いつもありがとうございます。 同じクラスの異なるインスタンスはここでしょうか??: @ObservedObject var fetchUsersViewModel = FetchUsersViewModel() ちなみに、Profile Header Viewにinit()を記載しその中でfetchUsersViewModelのfetchUserMe()を呼び出したらうまく行ったのですが、Profile Header Viewを表示してからViewが更新されるまでタイムラグがあるので、出来ればアプリ起動と同時にAPI通信したく、 成功した一番最初の書き方しかないでしょうか...?
xg63ex2b

2021/12/11 10:07

横から書き込みしてしまってすみません・・ hoshi-takanori さんのおっしゃる通り、Viewから参照しているのは直接的な`FetchUsersViewModel`のようです。 `AuthViewModel`の`FetchUsersViewModel`を参照している訳ではなさそうです。 > 同じクラスの異なるインスタンスはここでしょうか??: > @ObservedObject var fetchUsersViewModel = FetchUsersViewModel() そういうことだと思います。 `AuthViewModel`のfetchUsersViewModelを参照しないことには、思った通りにはならないように思います。 > 成功した一番最初の書き方しかないでしょうか...? そんなことはないとは思いますが、 文字で説明するのが大変になってきそうです・・ クラスの構造や処理の流れを整理してご自身で一つずつ理解するところから始めた方が良さそうです。 --- > (MVVMアーキテクチャにおいて何かタブーなことをやっているのかもしれません。。) 私自身、MVVMの理解が浅いのですが、 かつ、SwiftでのMVVMは、業務レベルでは皆無ですが、 ModelでやるべきことをViewModelでやってしまっているのではないか、 という気もします。 > ViewとViewModelでプレゼンテーション・ロジックを分担します。ViewModelはUI要素と結合しないプレゼンテーション・ロジックを担当し、ViewはUI要素に結合したプレゼンテーション・ロジックを担当します(具体的にはSystem.Windows名前空間ではじまる列挙体・構造体以外の型のプロパティはViewModelでは所持しないなどの切り分けが可能です)。 > > https://atmarkit.itmedia.co.jp/fdotnet/chushin/greatblogentry_02/greatblogentry_02_03.html . > MVVMにおいてはViewModel同士がお互いを操作する必要なんて基本的にはありません。所有関係はあることはありますがそもそもViewModelはModelの影なのです。そしてまたViewはViewModelの影でもあります。 > > https://ugaya40.hateblo.jp/entry/model-mistake (MVVMの発祥がC#な気がしておりますので、Swiftに関する質問ですが、あえてC#の記事を引用させていただきました)
ishiishiyay

2021/12/11 16:01

xg63ex2bさん、ご詳細に誠にありがとうございます!ViewModel同士がお互いを操作する必要ないんですね。関数をコールするだけならいいかなと思ってしまいました。設計の方法から勉強し直します!ありがとうございます。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています