xcode 12.4
iOS 14.0
これからSwift
でアプリを作成するにあたり、使い回せそうなコードを自分の都合でまとめました。
ライブラリ
pod
の準備
pod init
pod 'Firebase'
pod 'Firebase/Auth'
pod 'Firebase/Storage'
pod 'Firebase/Firestore'
pod 'SDWebImage'
pod "ViewAnimator"
pod 'ActiveLabel'
pod install
Firebase/Authを利用したログイン機能の実装(匿名ログイン)
FirebaseでGoogleServise-Info.plist
をダウンロードし、ファイル内に配置したら...
AppDelegate.swift
import Firebase
class AppDelegate: UIResponder, UIApplicationDelegate {
//(中略)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure() //<- 追加,firebaseauthを使うときに必要
return true
}
//(中略)
}
firebase/storageを利用したプロフィール画像設定機能の実装
カメラとアルバムの使用を許可するためのファイルの作成
Model/checkModel.swift
import Foundation
import Photos
class CheckModel {
func showCheckPermission() {
PHPhotoLibrary.requestAuthorization { (status) in
switch(status) {
case .authorized:
print("許可")
case .denied:
print("拒否")
case .notDetermined:
print("notDetermined")
case .restricted:
print("restricted")
case .limited:
print("limited")
@unknown default: break
}
}
}
}
ログインボタンの実装
Controller/LoginViewController.swift
import UIKit
import Firebase //<-追加
import FirebaseAuth //<-追加
class LoginViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
@IBOutlet weak var profileImageView: UIImageView! //<-storyboardと繋げる
@IBOutlet weak var textField: UITextField! //<-storyboardと繋げる
var sendDBModel = SendDBModel() //<-別途SendDBModelを作成 作成したModelを使用するためにインスタンス化が必要
var urlString = String() //<-クラウドに保存した画像のurlを利用するための箱
override func viewDidLoad() {
super.viewDidLoad()
//許可画面
let checkModel = CheckModel()
checkModel.showCheckPermission()
}
@IBAction func login(_ sender: Any) {
//匿名ログイン
Auth.auth().signInAnonymously { (result, error) in
//データベースのデータがresultに入る
//エラー処理
if error != nil {
return
}
//ユーザーが本当にいるのか
let user = result?.user
print(user.debugDescription)
//次の画面遷移 -> 次のViewControllerへ
let selectVC = self.storyboard?.instantiateViewController(identifier: "selectVC") as! selectRoomViewController
//アプリ内に名前を保存する forkeyはキー値
UserDefaults.standard.setValue(self.textField.text, forKey: "userName")
//画像をクラウドストレージに送信する + データを圧縮する
let data = self.profileImageView.image?.jpegData(compressionQuality: 0.01)
//データをストレージに保存する クラス名.sendProfileImageData(data: data)->classのメソッドに入る
self.sendDBModel.sendProfileImageData(data: data!)
//画面遷移
self.navigationController?.pushViewController(selectVC, animated: true)
}
}
}
プロフィール画像をFirebaseのDBに保存してアプリ内で使用するためのModel
Model/SendDBModel.swift
import Foundation
import FirebaseStorage
class SendDBModel {
//送信機能を集約するクラス
init () {
}
func sendProfileImageData(data:Data) {
let image = UIImage(data:data)
let profileImage = image!.jpegData(compressionQuality: 0.1)
//保存先の決定
//リファレンス パスを作り、フォルダを作成している UUIDで一意性のIDを作成し、uuid+dateでデータ名をつけている
let imageRef = Storage.storage().reference().child("profileImage").child("\(UUID().uuidString + String(Date().timeIntervalSince1970)).jpg")
//送信作業
imageRef.putData(profileImage!, metadata: nil) { (metadata, error) in
if error != nil {
return
}
//firebaseのサーバーから画像のurlが帰ってくる
imageRef.downloadURL { (url, error) in
if error != nil {
return
}
//userImageというキー値で画像を保存
UserDefaults.standard.setValue(url?.absoluteString, forKey: "userImage")
}
}
}
}
カメラとアルバムを使用するためのメソッド
Controller/LoginViewController.swift
func doCamera() {
let sourceType:UIImagePickerController.SourceType = .camera
//カメラ利用可能かチェック
if UIImagePickerController.isSourceTypeAvailable(.camera){
let cameraPicker = UIImagePickerController()
cameraPicker.allowsEditing = true
cameraPicker.sourceType = sourceType
cameraPicker.delegate = self
self.present(cameraPicker, animated: true, completion: nil)
}
}
func doAlbum() {
let sourceType:UIImagePickerController.SourceType = .photoLibrary
//アルバム利用可能かチェック
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
let cameraPicker = UIImagePickerController()
cameraPicker.allowsEditing = true
cameraPicker.sourceType = sourceType
cameraPicker.delegate = self
self.present(cameraPicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if info[.originalImage] as? UIImage != nil {
let selectedImage = info[.originalImage] as! UIImage
profileImageView.image = selectedImage
picker.dismiss(animated: true, completion: nil)
}
}
画像選択部分をタップするとアラートが出現し、カメラかアルバムか選択できるようにする
タップ機能が使用できるように、ImageView
のUser Interaction Enabled
に☑️をいれる。
Controller/LoginViewController.swift
@IBAction func tapImageView(_ sender: Any) {
let generater = UINotificationFeedbackGenerator()
generater.notificationOccurred(.success)
showAlert()
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
//アラート
func showAlert() {
let alertController = UIAlertController(title: "選択", message: "どちらを使用しますか?", preferredStyle: .actionSheet)
let action1 = UIAlertAction(title: "カメラ", style: .default) { (alert) in
self.doCamera()
}
let action2 = UIAlertAction(title: "アルバム", style: .default) { (alert) in
self.doAlbum()
}
let action3 = UIAlertAction(title: "キャンセル", style: .cancel)
alertController.addAction(action1)
alertController.addAction(action2)
alertController.addAction(action3)
self.present(alertController, animated: true, completion: nil)
}
//画面がタッチされたらキーボードを閉じる
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
textField.resignFirstResponder()
}
# キーボードを出現させたり隠れさせたりする
override func viewDidLoad() {
super.viewDidLoad()
//キーボード
//iphoneが持っている機能としてキーボードが呼ばれるとkeyboardwillshowが呼ばれる
NotificationCenter.default.addObserver(self, selector: #selector(EditViewController.keyboardWillShow(_ :)), name: UIResponder.keyboardWillShowNotification, object: nil)
//キーボードが隠れた時
NotificationCenter.default.addObserver(self, selector: #selector(EditViewController.keyboardWillHide(_ :)), name: UIResponder.keyboardWillHideNotification, object: nil)
if UserDefaults.standard.object(forKey: "userName") != nil {
userName = UserDefaults.standard.object(forKey: "userName") as! String
}
if UserDefaults.standard.object(forKey: "userImage") != nil {
userImageString = UserDefaults.standard.object(forKey: "userImage") as! String
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: true)
}
@objc func keyboardWillShow(_ notification:NSNotification) {
let keyboardHeight = ((notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as Any) as AnyObject).cgRectValue.height
//y座標は左上から始まる
//スクリーン全体の高さから、キーボードの高さと、テキストフィールドの高さを引いている
textField.frame.origin.y = screenSize.height - keyboardHeight - textField.frame.height
sendButton.frame.origin.y = screenSize.height - keyboardHeight - sendButton.frame.height
}
@objc func keyboardWillHide(_ notification:NSNotification) {
textField.frame.origin.y = screenSize.height - textField.frame.height
sendButton.frame.origin.y = screenSize.height - sendButton.frame.height
//キーボードが下がっていく時間がduration
//durationを渡してanimationを作成する
guard let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval else {return}
UIView.animate(withDuration: duration) {
let transform = CGAffineTransform(translationX: 0, y: 0)
self.view.transform = transform
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
textField.resignFirstResponder()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}