🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Firebase Authentication

Firebase Authenticationは、Firebaseを利用したユーザーの認証機能です。バックエンドサービス、SDK、アプリでのユーザー認証に使用できるUIライブラリが用意されています。

Swift

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

Q&A

解決済

2回答

1665閲覧

【SwiftUI】Firebaseを使ってのユーザー登録処理後の自動画面遷移(NavigationLink使用)ができません

liday

総合スコア12

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Firebase Authentication

Firebase Authenticationは、Firebaseを利用したユーザーの認証機能です。バックエンドサービス、SDK、アプリでのユーザー認証に使用できるUIライブラリが用意されています。

Swift

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

0グッド

0クリップ

投稿2022/11/24 22:14

編集2022/11/29 11:44

前提

SwiftUIとFirebaseを使って、Twitterのクローンアプリを作成しています。
その過程でユーザー情報の新規登録完了後、次のページに遷移したいのですが、うまくいきません。

ご参照いただきたいファイルは以下3つです。
1.AuthViewModel.swift → Firebaseを使用したユーザー登録のモデル情報
2.RegistrationView.swift → ユーザー新規登録Viewページの情報
3. CustomInputField.swift → RegistrationViewで使うユーザー入力フォーム

実現したいこと

  • Firebaseを使ってユーザー登録を完了したタイミングで、次のページに遷移したい。

発生している問題

RegistrationView.swift のページでユーザー情報を入力後、「Sign Up」ボタンを押すと、
遷移先のページが一瞬表示されるだけで、また空白のRegistrationView.swift ページが表示されてしまいます。

Firebase Consoleで確認しましたところ、ユーザーの登録情報は
Authentification、Firestore Databaseともにちゃんと登録されていました。

### ファイル1 AuthViewModel.swift

Swift

1import Firebase 2import FirebaseAuth 3import FirebaseStorage 4import FirebaseFirestore 5import FirebaseCore 6import SwiftUI 7 8class AuthViewModel: ObservableObject { 9 @Published var userSession: FirebaseAuth.User? 10 @Published var didAuthenticateUser = false 11 private var tempUserSession: FirebaseAuth.User? 12 13 init() { 14 self.userSession = Auth.auth().currentUser 15 16 print("DEBUG: User session is \(self.userSession?.uid)") 17 } 18 19 func register(withEmail email: String, password: String, fullname: String, username: String) { 20 Auth.auth().createUser(withEmail: email, password: password){ result, error in 21 if let error = error { 22 print("DEBUG: Failed to register with error \(error.localizedDescription)") 23 return 24 } 25 guard let user = result?.user else { return } 26 self.tempUserSession = user 27 28 let data = ["email": email, 29 "username": username.lowercased(), 30 "fullname": fullname, 31 "uid": user.uid] 32 33 Firestore.firestore().collection("users") 34 .document(user.uid) 35 .setData(data) { _ in 36 self.didAuthenticateUser = true 37 } 38 } 39 } 40} 41

### ファイル2 RegistrationView.swift

Swift

1 2import SwiftUI 3 4struct RegistrationView: View { 5 @State private var email = "" 6 @State private var username = "" 7 @State private var fullname = "" 8 @State private var password = "" 9 @EnvironmentObject var viewModel: AuthViewModel 10 11 var body: some View { 12 VStack{ 13 14 //以下のProfilePhotoSelectorView()は遷移したいページ先です。 15 NavigationLink(destination: ProfilePhotoSelectorView(), 16 isActive: $viewModel.didAuthenticateUser, 17 label: { }) 18 19 VStack(spacing: 40){ 20 CustomInputField(imageName: "envelope", placeholderText: "Email", text: $email) 21 CustomInputField(imageName: "person", placeholderText: "Username", text: $username) 22 CustomInputField(imageName: "person", placeholderText: "Full name", text: $fullname) 23 CustomInputField(imageName: "lock", placeholderText: "password",isSecureField: true, text: $password) 24 } 25 .padding(32) 26 27 Button { 28 viewModel.register(withEmail: email, password: password, fullname: fullname, username: username) 29 } label: { 30 Text("Sign Up") 31 } 32 Spacer() 33 } 34 } 35}

RegistrationView.swift のプレビュー画面

イメージ説明

### ファイル3 CustomInputField.swift

Swift

1import SwiftUI 2 3struct CustomInputField: View { 4 let imageName: String 5 let placeholderText: String 6 var isSecureField: Bool? = false 7 @Binding var text: String 8 9 var body: some View { 10 VStack{ 11 HStack{ 12 Image(systemName: imageName) 13 .resizable() 14 .scaledToFit() 15 .frame(width: 20, height: 20) 16 .foregroundColor(Color(.darkGray)) 17 18 if isSecureField ?? false { 19 SecureField(placeholderText, text: $text) 20 } else { 21 TextField(placeholderText, text: $text) 22 } 23 } 24 Divider() 25 .background(Color(.darkGray)) 26 } 27 } 28} 29 30struct CustomInputField_Previews: PreviewProvider { 31 static var previews: some View { 32 CustomInputField(imageName: "envelope", placeholderText: "Email", isSecureField: false, text: .constant("")) 33 } 34}

主に試したこと

その1 NavigationLinkのNavigationStackへの書き換え

RegistrationView.swift 内の記述において、ページ遷移のためにNavigationLinkを記述しているのですが、
Xcodeのアラート表示で「'init(destination:isActive:label:)' was deprecated in iOS 16.0: use NavigationLink(value: label:) inside a NavigationStack or NavigationSplitView」と出るため、
NavigationStackを使った記述に変更しようとしたのですが、
isActiveをどう書き換えれば良いかわからず、うまくいきません。

以下参照した記事

▼iOS 16 以降で非推奨となった NavigationLink の isActive の代わりの書き方は?
https://ja.stackoverflow.com/questions/90726/ios-16-%E4%BB%A5%E9%99%8D%E3%81%A7%E9%9D%9E%E6%8E%A8%E5%A5%A8%E3%81%A8%E3%81%AA%E3%81%A3%E3%81%9F-navigationlink-%E3%81%AE-isactive-%E3%81%AE%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9%E3%81%AF

▼NavigationViewの不満点をNavigationStackで解決する
https://zenn.dev/chocoyama/articles/32d52cf66dd6ff

その2 import内容を変更

FIrebaseのインポート情報が足りたいのかもしれないと思い、
AuthViewModel.swiftの冒頭でたくさんimportしてみましたが、改善はありません。

以上、大変恐れ入りますが、解決策の心当たりがございましたらお教えください。
何卒よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

Xcode Version 14.1

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

解決いたしました。

原因・解決法

@mainの記載があるファイル内のコードが原因でした。
具体的にどのコードが直接の原因だったのかはまだわかっていません。

Firebaseコンソールでiosを登録する際に表示されるコードをそのまま使用しており、今回の問題が起こるまでアプリが問題なく動作しておりましたため、質問に掲載していないこのファイルに原因があることに気づけませんでした。

大変申し訳ございませんでした。

変更前のソースコード

swift

1import SwiftUI 2import FirebaseCore 3 4class AppDelegate: NSObject, UIApplicationDelegate { 5 func application(_ application: UIApplication, 6 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 7 FirebaseApp.configure() 8 return true 9 } 10} 11 12@main 13struct TwitterLikeApp: App { 14 15 @StateObject var viewModel = AuthViewModel() 16 // register app delegate for Firebase setup 17 @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate 18 19 var body: some Scene { 20 WindowGroup { 21 NavigationView { 22 ContentView() 23 } 24 .environmentObject(viewModel) 25 } 26 } 27}

変更後のソースコード

swift

1import SwiftUI 2import Firebase 3 4@main 5struct TwitterLikeApp: App { 6 7 @StateObject var viewModel = AuthViewModel() 8 9 init(){ 10 FirebaseApp.configure() 11 } 12 13 var body: some Scene { 14 WindowGroup { 15 NavigationView { 16 ContentView() 17 } 18 .environmentObject(viewModel) 19 .navigationViewStyle(StackNavigationViewStyle()) 20 } 21 } 22}

投稿2022/11/30 23:25

liday

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

RegistrationView.swift のページでユーザー情報を入力後、「Sign Up」ボタンを押すと、
遷移先のページが一瞬表示されるだけで、また空白のRegistrationView.swift ページに戻ってしまいます。

手元にFirebaseを試せる環境がないので、、
それらを取り除いてシンプルな形で再現確認してみたところ(一旦NavigationViewを使って)、
遷移先のページは表示されるように見えました。
*質問欄には記載されていないコードに影響されているのかな?と思いました

*ただ、全体の画面遷移の形をよく把握していないのですが、Navigationで大丈夫かな?と思ったりもします

swift

1// ContentView.swift 2import SwiftUI 3struct ContentView: View { 4 @State private var obj = AuthViewModel() 5 var body: some View { 6 NavigationView { 7 RegistrationView() 8 .environmentObject(obj) 9 } 10 } 11} 12 13// AuthViewModel.swift 14import SwiftUI 15class AuthViewModel: ObservableObject { 16 @Published var didAuthenticateUser = false 17 func register(withEmail email: String, password: String, fullname: String, username: String) { 18 print("register") 19 didAuthenticateUser = true 20 } 21} 22 23// RegistrationView 24import SwiftUI 25struct RegistrationView: View { 26 @State private var email = "" 27 @State private var username = "" 28 @State private var fullname = "" 29 @State private var password = "" 30 @EnvironmentObject var viewModel: AuthViewModel 31 var body: some View { 32 VStack{ 33 NavigationLink(destination: ProfilePhotoSelectorView(), 34 isActive: $viewModel.didAuthenticateUser, 35 label: { }) 36 VStack(spacing: 40){ 37 CustomInputField(imageName: "envelope", placeholderText: "Email", text: $email) 38 CustomInputField(imageName: "person", placeholderText: "Username", text: $username) 39 CustomInputField(imageName: "person", placeholderText: "Full name", text: $fullname) 40 CustomInputField(imageName: "lock", placeholderText: "password",isSecureField: true, text: $password) 41 } 42 .padding(32) 43 Button { 44 viewModel.register(withEmail: email, password: password, fullname: fullname, username: username) 45 } label: { 46 Text("Sign Up") 47 .font(.headline) 48 .foregroundColor(.white) 49 .frame(width: 340, height: 50) 50 .background(Color(.systemBlue)) 51 .clipShape(Capsule()) 52 .padding() 53 } 54 .shadow(color: .gray.opacity(0.5), radius: 10, x: 0, y:0) 55 Spacer() 56 } 57 } 58} 59 60struct ProfilePhotoSelectorView: View { 61 var body: some View { 62 Text("ProfilePhotoSelectorView") 63 } 64} 65 66struct CustomInputField: View { 67 var imageName: String 68 var placeholderText: String 69 var isSecureField: Bool = false 70 @Binding var text: String 71 var body: some View { 72 Text("CustomInputField") 73 } 74}

NavigationStackを使うとしたら
次のような感じかなと思いました。
*私自身勉強しながら書いてみましたので、正しくない記述もあるかもしれません・・

swift

1// ContentView.swift 2import SwiftUI 3struct ContentView: View { 4 // NavigationStackのpathです。 5 @State private var path: [String] = [] 6 @State private var obj = AuthViewModel() 7 var body: some View { 8 NavigationStack(path: $path) { 9 RegistrationView(path: $path) 10 .environmentObject(obj) 11 } 12 } 13} 14 15// AuthViewModel.swift 16import SwiftUI 17class AuthViewModel: ObservableObject { 18 @Published var didAuthenticateUser = false 19 func register(withEmail email: String, password: String, fullname: String, username: String) { 20 print("register") 21 didAuthenticateUser = true 22 } 23} 24 25// RegistrationView 26import SwiftUI 27struct RegistrationView: View { 28 // NavigationStackのpathをBindingします。 29 @Binding var path: [String] 30 @State private var email = "" 31 @State private var username = "" 32 @State private var fullname = "" 33 @State private var password = "" 34 @EnvironmentObject var viewModel: AuthViewModel 35 var body: some View { 36 VStack{ 37 VStack(spacing: 40){ 38 CustomInputField(imageName: "envelope", placeholderText: "Email", text: $email) 39 CustomInputField(imageName: "person", placeholderText: "Username", text: $username) 40 CustomInputField(imageName: "person", placeholderText: "Full name", text: $fullname) 41 CustomInputField(imageName: "lock", placeholderText: "password",isSecureField: true, text: $password) 42 } 43 .padding(32) 44 Button { 45 viewModel.register(withEmail: email, password: password, fullname: fullname, username: username) 46 } label: { 47 Text("Sign Up") 48 .font(.headline) 49 .foregroundColor(.white) 50 .frame(width: 340, height: 50) 51 .background(Color(.systemBlue)) 52 .clipShape(Capsule()) 53 .padding() 54 } 55 .shadow(color: .gray.opacity(0.5), radius: 10, x: 0, y:0) 56 Spacer() 57 } 58 // didAuthenticateUserが変わったらpathを設定します。 59 .onChange(of: viewModel.didAuthenticateUser) { newValue in 60 print(newValue) 61 path.append("ProfilePhotoSelectorView") 62 } 63 // pathが変わったらProfilePhotoSelectorViewを表示します。 64 .navigationDestination(for: String.self, destination: { _ in 65 ProfilePhotoSelectorView() 66 }) 67 } 68} 69 70struct ProfilePhotoSelectorView: View { 71 var body: some View { 72 Text("ProfilePhotoSelectorView") 73 } 74} 75 76struct CustomInputField: View { 77 var imageName: String 78 var placeholderText: String 79 var isSecureField: Bool = false 80 @Binding var text: String 81 var body: some View { 82 Text("CustomInputField") 83 } 84} 85 86struct RegistrationView_Previews: PreviewProvider { 87 @State static private var path: [String] = [] 88 static var previews: some View { 89 RegistrationView(path: $path) 90 } 91}

投稿2022/11/26 02:39

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

liday

2022/11/29 12:08 編集

回答いただきありがとうございます! また、CustomInputFieldの記述が漏れておりました、大変申し訳ございません! ご指摘いただきました通り、記載以外の部分(Firebaseの何らか?)が影響しているのかもしれません。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問