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

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

ただいまの
回答率

88.77%

addSnapshotListenerを使ってデータをリアルタイムで更新すると、画面が自動で遷移してしまう

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 482

Natsu.mikan

score 6

FirestoreとSwiftを使用して、お気に入りの映画を登録するアプリを開発しています。

画面構成

  • お気に入りの映画の一覧画面(初期画面)
  • すべての映画一覧画面
  • 映画の詳細画面(お気に入りに追加できる)

困っていること

お気に入りに映画を追加するために、

  1. 「MovieSearchView」に遷移
  2. 映画を選択し、「MovieDetailView」に遷移
  3. 「Add」ボタンをクリック
    と操作すると、MovieDetailViewから自動的にMovieSearchViewに遷移してしまいました。

「Add」ボタンを押しても「MovieDetailView」にとどまるにはどうしたらいいですか?

import SwiftUI
import FirebaseFirestore
import Foundation

struct FavoriteMovieListView: View {
    @ObservedObject var favoriteMoviesFetcher = FavoriteMoviesFetcher()
    @State private var modalPresented: Bool = false

    var body: some View {
      VStack {
            Button(action: {
                self.modalPresented.toggle()
            }) {
                Text("Search")
            }
            .sheet(isPresented: self.$modalPresented) {
                MovieSearchView(onDismiss: {
                    self.modalPresented = false
                })
            }

            List(self.favoriteMoviesFetcher.data) { movie in
                Text(movie.title)
            }
        }
    }
}

struct MovieSearchView: View {
    @ObservedObject var allMovieFetcher = AllMovieFetcher()
    var onDismiss: () -> ()

    var body: some View {
        NavigationView {
            List(allMovieFetcher.data) { movie in
                NavigationLink(
                    destination: MovieDetailView(
                        movie: movie
                    )
                ) {
                    Text(movie.title)
                }
            }
        }
    }
}

struct MovieDetailView: View {
    @State var movie: MovieModel

    var body: some View {
        Button(action: {
            FavoriteMoviesService().addMovie(movie: self.movie)
        }) {
            Text("Add")
        }
    }
}

class FavoriteMovieFetcher: ObservableObject {
    @Published var data: [MovieModel] = []

    private var db: Firestore!
    private var uid: String

    init() {
        db = Firestore.firestore()
        uid = UserDefaults.standard.object(forKey: "userUid") as! String

        fetchData()
    }

    private func fetchData() {
        self.db.collection("favoriteMovies/\(uid)/movies").addSnapshotListener { querySnapshot, error in

            guard let snapshot = querySnapshot else {
                print("Error fetching snapshots: \(error!)")
                return
            }

            snapshot.documentChanges.forEach { diff in
                if (diff.type == .added) {
                    self.data.append(MovieModel(
                        movieId: diff.document.documentID,
                        title: diff.document.data()["title"]as! String
                    ))
                } else if (diff.type == .modified) {

                } else if (diff.type == .removed) {
                    self.data = self.data.filter { $0.movieId != diff.document.documentID }
                }
            }

            self.isLoading = false
        }
    }
}

class AllMovieFetcher: ObservableObject {
    @Published var data: [MovieModel] = []
    private var db: Firestore!

    init() {
        db = Firestore.firestore()
        fetchData()
    }

    private func fetchData() {
        self.db.collection("movies").getDocuments { (snaps, err) in
            if let err = err {
                print("Error getting documents: \(err)")
            }

            guard let snaps = snaps else { return }

            for document in snaps.documents {
                    self.data.append(
                        MovieModel(
                            movieId: document.documentID,
                            title: document.data()["title"]as! String
                        )
                    )
            }
        }
    }
}

class FavoriteMoviesService: ObservableObject {
    private var db: Firestore!
    private var uid: String

    init() {
        db = Firestore.firestore()
        uid = UserDefaults.standard.object(forKey: "userUid") as! String
    }

    func addMovie(movie: MovieModel) {
        self.db.collection("favoriteMovies/\(uid)/movies").document(movie.movieId).setData([
            "title": movie.title
        ]) { err in
            if let err = err {
                print("Error adding document: \(err)")
            } else {

            }
        }
    }
}

struct MovieModel: Identifiable {
    var id = UUID()
    var movieId: String
    var title: String
}

self.db.collection("favoriteMovies/\(uid)/movies").addSnapshotListener

ではなく、

self.db.collection("favoriteMovies/\(uid)/movies").getDocuments

とすると遷移しなかったですが、
追加時にお気に入り一覧を更新したいので.addSnapshotListenerを使って実現する方法が知りたいです。
よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

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

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

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

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

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

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

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

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

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

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