Swift Firebase ユーザーのアイコンとニックネーム登録(Storage & Authentication)


概要

  • iOSアプリを開発している
  • Firebaseを使いたい
  • ユーザーのアイコン、ニックネームを登録したい

説明

現在開発中のアプリ(クイズのオンライン対戦)でユーザーのアイコンとニックネームが必要となりました。
概要のとおり、個人アプリを開発時に良くあるケースですが、
Qiitaなどでサンプルコードがすぐに見つからないので共有しておきます。

要件

  • アイコンをタップするとpickerでphotoLibraryから画像選択
  • ニックネームはtextFieldで変更
  • 保存ボタンタップ時にputData()でアイコンをstorageに登録
  • アイコンurlとニックネームを更新

結果

サンプルコード

import Foundation
import UIKit
import Firebase
import FirebaseStorage

class ProfileViewController: UIViewController {

    @IBOutlet weak var nickNameTextField: UITextField!
    @IBOutlet weak var imageButton: UIButton! {
        didSet {
            imageButton.imageView?.contentMode = .scaleAspectFill
            imageButton.imageView?.layer.cornerRadius = 60
            imageButton.imageView?.layer.borderWidth = 0.5
            imageButton.imageView?.layer.borderColor = UIColor.lightGray.cgColor
        }
    }

    let user: User?
    let icon: UIImage?
    private let maxNameLength = 10
    private let storageRef = Storage.storage().reference()
    private var picker = UIImagePickerController()

    init(user: User?, icon: UIImage?) {
        self.user = user
        self.icon = icon
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "プロフィール"
        nickNameTextField.text = user?.displayName
        imageButton.setImage(icon, for: .normal)

        picker.delegate = self
        picker.sourceType = .photoLibrary
        picker.view.backgroundColor = .white
    }    

    private func signInAnonymously(displayName: String?, photoURL: URL?) {
        Auth.auth().signInAnonymously { [weak self] (authResult, error) in
            guard let user = authResult?.user else { return }
            let request = user.createProfileChangeRequest()
            request.displayName = self?.nickNameTextField.text
            request.photoURL = photoURL
            request.commitChanges { [weak self] (error) in
                if error == nil {
                    self?.navigationController?.popViewController(animated: true)
                    self?.navigationController?.dismiss(animated: true, completion: nil)
                }
            }
        }
    }

    @IBAction func didTapSaveButton(_ sender: Any) {
        guard let uid = user?.uid else { return }
        guard let imageData = imageButton.imageView?.image?.cropImage()?.jpegData(compressionQuality: 0.3) else { return }
        let imageRef = storageRef.child("images/\(uid).jpg")
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpeg"
        let _ = imageRef.putData(imageData, metadata: metadata) { [weak self] (metadata, error) in
            guard let _ = metadata else { return }
            imageRef.downloadURL { (url, error) in
                guard let photoURL = url else { return }
                self?.signInAnonymously(displayName: self?.nickNameTextField.text, photoURL: photoURL)
            }
        }
    }

    @IBAction func didTapImage(_ sender: Any) {
        present(picker, animated: true, completion: nil)
    }
}

extension ProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let editedImage = info[.editedImage] as? UIImage {
            imageButton.setImage(editedImage, for: .normal)
        } else if let originalImage = info[.originalImage] as? UIImage {
            imageButton.setImage(originalImage, for: .normal)
        }
        dismiss(animated: true, completion: nil)
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }
}