Edited at

FireBase Authenticationを使ってみた 8/12更新

初投稿です!

プログラミング初心者です。

メモとして残してみました。

Swift勉強していたらFireBaseがなんか良いと聞いたので使ってみました。

参考ページ

https://qiita.com/matsuei/items/4f56c0f8d9a1b96cd9f0


FireBaseとは

https://www.topgate.co.jp/firebase01-what-is-firebase

google様が出してる便利なやつ!

今回はLogin 機能を作ってみました!



押したら



形変だけど



できました。

今回は設定にハマりました。

最終的にgoogleだけにしたらエラーにならなくてすみました。

コードはほぼコピペでいけました。

あとは通常のログイン画面をつければ、良いかなって考えてます。


ViewController.swift

import UIKit

import Firebase
import FirebaseUI

class ViewController: UIViewController, FUIAuthDelegate {

@IBOutlet weak var AuthButton: UIButton!

var authUI: FUIAuth { get { return FUIAuth.defaultAuthUI()!}}

let providers: [FUIAuthProvider] = [ FUIGoogleAuth() ]

override func viewDidLoad() {
super.viewDidLoad()

self.authUI.delegate = self
self.authUI.providers = providers
AuthButton.addTarget(self,action: #selector(self.AuthButtonTapped(sender:)),for: .touchUpInside)
}

@objc func AuthButtonTapped(sender : AnyObject) {
// FirebaseUIのViewの取得
let authViewController = self.authUI.authViewController()
// FirebaseUIのViewの表示
self.present(authViewController, animated: true, completion: nil)
}

public func authUI(_ authUI: FUIAuth, didSignInWith user: User?, error: Error?){
// 認証に成功した場合
if error == nil {
self.performSegue(withIdentifier: "OK", sender: self)
}
print("error")
}
}



AppDelegate.swift

import UIKit

import Firebase
import FirebaseUI

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
override init() {
super.init()
FirebaseApp.configure()
}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

// Override point for customization after application launch.
return true
}

func application(_ app: UIApplication, open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
let sourceApplication = options[UIApplication.OpenURLOptionsKey.sourceApplication] as! String?

if FUIAuth.defaultAuthUI()?.handleOpen(url, sourceApplication: sourceApplication) ?? false {
return true
}
return false


あと、

GoogleService-Info.plist

をダウンロードして追加。

この辺は公式に書いてある通りにしました!


FireBaseUIをもう一度使ってみた


  • FaceBook

FaceBookdeveloper で設定をする。

ここはググる。と出てくる。そんなに難しくない。

あとは公式と参考記事見ながらやるとすぐにできる。


  • Twitter

    なんか申請とか大変そうで時間ないのでやらない。


  • GOOGLE


GoogleService-Info.plist > REVERSED_CLIENT_ID : Valueの部分をコピー

TOP > TARGETS > Info > URL Type > URL Schemes に貼り付け


  • 電話認証

オンにする。

xcodeにURLを貼るか証明書を作成する。

証明書は一旦証明書の土台?をローカルで作成して

それからそれをAPPLEDeveloperで設定したやつに貼り付ける。(AppleDeveloperの中で)

下記のコードをAppDelegateに書かないとえらる。

func application(_ application: UIApplication,

didReceiveRemoteNotification notification: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if Auth.auth().canHandleNotification(notification) {
completionHandler(UIBackgroundFetchResult.noData)
return
}
}

参考記事

https://qiita.com/matsuei/items/4f56c0f8d9a1b96cd9f0


Firebase Authenticationを使う 8/11追加

参考記事

https://dev.classmethod.jp/smartphone/iphone/firebase-authentication-ios/

やったこと

Viewを3つ(signup, login, confirmation)つくる

Firebaseの設定(project作ってGoogleService-Info.plistをxcodeに貼る)

やっている仕組みはまだ完璧に理解できてない。






SignUpViewController.swift


import UIKit
import Firebase

final class SignUpViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var signupNameTextField: UITextField!
@IBOutlet weak var signupMailTextField: UITextField!
@IBOutlet weak var signupPWTextField: UITextField!
@IBOutlet weak var signupPWCTextField: UITextField!
@IBOutlet weak var SignUpButton: UIButton!

override func viewDidLoad() {
super.viewDidLoad()
self.SignUpButton.addTarget(self, action: #selector(SignUp), for: .touchUpInside)
self.signupNameTextField.delegate = self
self.signupMailTextField.delegate = self
self.signupPWTextField.delegate = self
self.signupPWCTextField.delegate = self
}

@objc private func SignUp() {
guard let name = signupNameTextField.text else { return }
guard let mail = signupMailTextField.text else { return }
guard let pw = signupPWTextField.text else { return }
guard let pwc = signupPWCTextField.text else { return }
if pw == pwc {
FireBaseSignUp(name, mail, pw)
} else {
let alert = UIAlertController(title: "エラー", message: "パスワードが一致しません", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default)
alert.addAction(action)
present(alert, animated: true)
}
}

private func FireBaseSignUp(_ name: String,_ mail: String,_ pw: String) {
Auth.auth().createUser(withEmail: mail, password: pw) { result, error in
if let user = result?.user {
self.updateDisplayName(name, of: user)
}
self.FireBaseError(error)
}
}

private func updateDisplayName(_ name: String, of user: User) {
let request = user.createProfileChangeRequest()

request.commitChanges() { error in
if error != nil {
self.FireBaseError(error)
}
self.sendEmailVerification(user)
}
}

private func sendEmailVerification(_ user: User) {
user.sendEmailVerification() { error in
print()
if error != nil {
self.FireBaseError(error)
}
self.TransitionToCofirmationView()
}
}

private func TransitionToCofirmationView() {
let alert = UIAlertController(title: "成功", message: "登録が完了しました", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default, handler: {_ in
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.present(vc, animated: true)
})
alert.addAction(action)
self.present(alert, animated: true)
}
@IBAction func BackToLoginView(_ sender: UIBarButtonItem) {
self.performSegue(withIdentifier: "LoginView", sender: nil)
}

internal func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if (self.signupNameTextField.isFirstResponder) {
signupNameTextField.resignFirstResponder()
} else if (self.signupMailTextField.isFirstResponder) {
signupMailTextField.resignFirstResponder()
} else if (self.signupPWTextField.isFirstResponder) {
signupPWTextField.resignFirstResponder()
} else if (self.signupPWCTextField.isFirstResponder) {
signupPWCTextField.resignFirstResponder()
}
}

private func FireBaseError(_ errorOrNil: Error?) {
guard let error = errorOrNil else { return }

let message = Errors().errorMessage(of: error)
let alert = UIAlertController(title: "", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alert, animated: true)
}
}



viewController.swift


import UIKit
import Firebase

class ViewController: UIViewController {

var handle: AuthStateDidChangeListenerHandle?

override func viewDidLoad() {
super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool) {
handle = Auth.auth().addStateDidChangeListener { (auth, user) in
if let user = user {
let _ = user.displayName
}
}
print(handle as Any)
}

override func viewDidAppear(_ animated: Bool) {
if let handle = handle {
Auth.auth().removeStateDidChangeListener(handle)
}
}

@IBAction func Logout(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "確認", message: "ログアウトしますか?", preferredStyle: .alert)
let logoutAction = UIAlertAction(title: "OK", style: .default, handler: { _ in
do {
try Auth.auth().signOut()
self.performSegue(withIdentifier: "ToLoginView", sender: nil)
} catch let error {
self.FireBaseError(error)
}
})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addAction(logoutAction)
alert.addAction(cancelAction)
self.present(alert, animated: true)
}

@IBAction func DestroyAccount(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "確認", message: "退会しますか?", preferredStyle: .alert)
let logoutAction = UIAlertAction(title: "OK", style: .default, handler: { _ in
Auth.auth().currentUser?.delete() { error in
if error != nil {
self.FireBaseError(error)
}
self.performSegue(withIdentifier: "ToLoginView", sender: nil)
}
})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addAction(logoutAction)
alert.addAction(cancelAction)
self.present(alert, animated: true)
}

private func FireBaseError(_ errorOrNil: Error?) {
guard let error = errorOrNil else { return }

let message = Errors().errorMessage(of: error)
let alert = UIAlertController(title: "", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alert, animated: true)
}
}



login.swift


import UIKit
import Firebase

final class LoginViewController: UIViewController, UITextFieldDelegate{

@IBOutlet weak var loginMailTextField: UITextField!
@IBOutlet weak var loginPWTextfield: UITextField!
@IBOutlet weak var loginButton: UIButton!

override func viewDidLoad() {
super.viewDidLoad()
self.loginButton.addTarget(self, action: #selector(Login), for: .touchUpInside)
loginPWTextfield.delegate = self
loginMailTextField.delegate = self
}

@IBAction func ForgetPassWord(_ sender: UIButton) {
}

@objc private func Login() {
guard let mail = loginMailTextField.text else { return }
guard let pw = loginPWTextfield.text else { return }

Auth.auth().signIn(withEmail: mail, password: pw) { result, error in
if (result?.user) != nil {
let alert = UIAlertController(title: "成功", message: "ログインできました", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default, handler: { _ in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.present(vc, animated: true)
})
alert.addAction(action)
self.present(alert, animated: true)
}
self.FireBaseError(error)
}
}

@IBAction func TransitionToSignUpView(_ sender: UIBarButtonItem) {
performSegue(withIdentifier: "SignUpView", sender: nil)
}

internal func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if (self.loginPWTextfield.isFirstResponder) {
loginPWTextfield.resignFirstResponder()
} else if (self.loginMailTextField.isFirstResponder) {
loginMailTextField.resignFirstResponder()
}
}

private func FireBaseError(_ errorOrNil: Error?) {
guard let error = errorOrNil else { return }

let message = Errors().errorMessage(of: error)
let alert = UIAlertController(title: "", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alert, animated: true)
}
}


これでconfirmationはただラベル置くだけ。

Errorのハンドリング?が毎回あってそれをもっとまとめたいって思ったのですが、うまくいかず断念。

考え方があっているかどうかわからないが、エラークラスにまとめたかった。


Error.swift


import UIKit
import Firebase

final class Errors {
func errorMessage(of error: Error) -> String {
var message = "エラーが発生しました"
guard let errcd = AuthErrorCode(rawValue: (error as NSError).code) else {
return message
}

switch errcd {
case .networkError: message = "ネットワークに接続できません"
case .userNotFound: message = "ユーザが見つかりません"
case .invalidEmail: message = "不正なメールアドレスです"
case .emailAlreadyInUse: message = "このメールアドレスは既に使われています"
case .wrongPassword: message = "入力した認証情報でログインできません"
case .userDisabled: message = "このアカウントは無効です"
case .weakPassword: message = "パスワードが脆弱すぎます"
default: break
}
return message
}
}


参考記事

https://dev.classmethod.jp/smartphone/iphone/firebase-authentication-ios/

公式ドキュメント