• save images to Firestore
  • fetch images when it loads settings
  • reflect more images
  • update toCardViewModel()

Save image to Firestore in imagePickerController

When we pick an image on selectPhoto button, an image data is stored in firestore using putData().

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        ...
        
        let filename = UUID().uuidString
        let ref = Storage.storage().reference(withPath: "/images/\(filename)")
        guard let uploadData = selectedImage?.jpegData(compressionQuality: 0.75) else { return }
        let hud = JGProgressHUD(style: .dark)
        hud.textLabel.text = "Uploading image..."
        hud.show(in: view)
        ref.putData(uploadData, metadata: nil) { (_, err) in
            hud.dismiss()
            if let err = err {
                print("Failed to upload image to storage", err)
                return
            }
            print("Finished uploading image")
        }
    }

generate random string value

let filename = UUID().uuidString

guard for unwrapping

But we didn’t save them to Firebase database as URL. We gotta save them as new key.

After we put data, downloadURL on ref, this url should be updated to User Model and Firebase.

        ref.putData(uploadData, metadata: nil) { (_, err) in
            if let err = err {
                hud.dismiss()
                print("Failed to upload image to storage", err)
                return
            }
            
            print("Finished uploading image")
            ref.downloadURL(completion: { (url, err) in
                
                hud.dismiss()
                
                if let err = err {
                    print("Failed to retrieve download URL :", err)
                    return
                }
                
                print("Finished getting download url :", url?.absoluteString ?? "")
            })
        }

Model 수정하기

how to keep tracking images

    var imageUrl1: String?
    var imageUrl2: String?
    var imageUrl3: String?
self.imageUrl1 = dictionary["imageUrl1"] as? String ?? ""

imageUrl properties are optional, so ?? ""을 사용할 필요가 없다.

UIImagePickerDelegate에서 위임시키고 가져온 함수, imagePickerController에서 이미지를 선택할 때마다 user를 업데이트 해주고

// func imagePickerController() by UIImagePickerDelegate
                if imageButton == self.image1Button {
                    self.user?.imageUrl1 = url?.absoluteString
                } else if imageButton == self.image2Button {
                    self.user?.imageUrl2 = url?.absoluteString
                } else {
                    self.user?.imageUrl3 = url?.absoluteString
                }

handleSave()에서 setData()로 firebase DB를 업데이트를 해줄 dictionary에도 유저 값을 가져와 변경해준다.

// func handleSave()
        let docData: [String: Any] = [
            "uid": uid,
            "fullName": user?.name ?? "",
            "imageUrl1": user?.imageUrl1 ?? "",
            "imageUrl2": user?.imageUrl2 ?? "",
            "imageUrl3": user?.imageUrl3 ?? "",
            "age": user?.age ?? -1,
            "profession": user?.profession ?? ""
        ]

사실 이렇게 imagePickerController에서 선택할 때 마다 firestore에 먼저 저장하면 비효율적이다.


다시 Settings에 들어가면 data들이 fetch되지 않았다. fetch해오는 과정을 업데이트 해주자!

imageUrl1만 fetch해오고 있었다.

    fileprivate func loadUserPhotos() {
        guard let imageUrl = self.user?.imageUrl1, let url = URL(string: imageUrl) else { return }
        // why exactly do we use this SDWebImageManager class to load our images?
        SDWebImageManager.shared().loadImage(with: url, options: .continueInBackground, progress: nil) { (image, _, _, _, _, _) in
            self.image1Button.setImage(image?.withRenderingMode(.alwaysOriginal), for: .normal)
        }
    }

guard -> if로 변경

    fileprivate func loadUserPhotos() {
        if let imageUrl = self.user?.imageUrl1, let url = URL(string: imageUrl) {
            SDWebImageManager.shared().loadImage(with: url, options: .continueInBackground, progress: nil) { (image, _, _, _, _, _) in
                self.image1Button.setImage(image?.withRenderingMode(.alwaysOriginal), for: .normal)
            }
        }
        if let imageUrl = self.user?.imageUrl2, let url = URL(string: imageUrl) {
            SDWebImageManager.shared().loadImage(with: url, options: .continueInBackground, progress: nil) { (image, _, _, _, _, _) in
                self.image1Button.setImage(image?.withRenderingMode(.alwaysOriginal), for: .normal)
            }
        }
        if let imageUrl = self.user?.imageUrl2, let url = URL(string: imageUrl) {
            SDWebImageManager.shared().loadImage(with: url, options: .continueInBackground, progress: nil) { (image, _, _, _, _, _) in
                self.image1Button.setImage(image?.withRenderingMode(.alwaysOriginal), for: .normal)
            }
        }
    }

User에서 CardViewModel로 가는 과정도 업데이트 해줘야한다!

// User.swift 
    func toCardViewModel() -> CardViewModel {
        ...
        return CardViewModel(imageNames: [imageUrl1 ?? "", imageUrl2 ?? "", imageUrl3 ?? ""], attributedString: attributedText, textAlignment: .left)
    }

it happens bug because we are using empty string.

        var imageUrls = [String]() // empty string array
        if let url = imageUrl1 { imageUrls.append(url) }
        if let url = imageUrl2 { imageUrls.append(url) }
        if let url = imageUrl3 { imageUrls.append(url) }
        
        return CardViewModel(imageNames: imageUrls, attributedString: attributedText, textAlignment: .left)

이렇게 unwrapping을 해주면 주소가 명시되어있지 않은 이미지는 아예 인자로 들어가지 못하게 된다.

optional + unwrapping의 너무 좋은 활용!

태그: ,

카테고리:

업데이트:

댓글남기기