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

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

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

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

# 結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117784/65f3731c-321b-b998-d81d-0c8b3aab73ea.gif" width="400">



# サンプルコード
```swift
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)
    }
}
```