Swift 용 Firebase RealtimeDB + Storage의 이미지로드 라이브러리를 만들었습니다.

최근 Firebase를 백엔드로 한 앱을 잘 개발하고 있습니다만 RealtimeDB, Storage, TableView 로 문제에 부딪쳤으므로 해결을 위해 라이브러리를 만들었습니다.
Firebase RealtimeDB, Storage 에 대해서는 Salada 를 이용하고 있는 전제입니다.

Firebase RealtimeDB+Storage로 인한 이미지 로드 문제



TableViewCell + ImageView에서 다음과 같은 문제가 발생합니다.
  • cellForRowAtIndexPath에서 Model 가져 오기
  • ImageView에 이미지를 로드
  • 로드가 끝나기 전에 스크롤
  • cell 가 reuse 된다
  • 다음 indexPath 로 다른 이미지를 로드
  • 첫 번째 이미지가 순식간에 표시되고 적절한 이미지가 표시됩니다.
    class MyTableViewCell {
        @IBOutlet weak var imageView: UIImageView!
    
        func configure(id: String) {
            Firebase.User.observeSingle(id: id, type: .value) { user in
                guard let user: Firebase.User = user else { return }
                if let profileImageRef = user.profileImage.ref {
                    imageView.sd_setImage(ref)
                }
            }
        }
    
        func prepareForReuse() {
            imageView.image = nil
        }
    }
    

    이 문제는 셀 내 이중 비동기 통신으로 인해 발생하며 다음과 같은 그림으로 나타낼 수 있습니다.



    해결책



    여기서 발생하는 문제는 다음 두 가지입니다.
  • 셀 재설정 중에 이미지 다운로드를 취소하지 않았습니다
  • imageView의 image를 set 할 때 올바른 이미지인지 여부를 결정하지 않습니다.

    우선, cell の reuse 時に画像ダウンロードをキャンセルしていない 로부터 해결해 갑니다.
    이것은 UIImageView 의 extention 에 cancelLoading() suspendLoading() 를 구현했습니다.
    이러한 방법 중 하나를 호출하여 이미지 로드를 중지하고 취소할 수 있습니다.
    다음에 imageView の image を set する時に、正しい画像かどうかを判定していない 에 관해서는 load 시에 Bool 를 반환값에 취하는 블록을 건네주는 것으로, 그 조건을 만족했을 경우만 이미지를 set 하게 하는 메소드 load(_ storageReference: StorageReference, shouldSetImageConditionBlock: @escaping (() -> Bool) = { return true } ) 를 UIImageView 의 extension 에 구현했습니다.

    이것에 의해 최종적인 셀의 구현은 이런 느낌이 됩니다.
    class MyTableViewCell {
        @IBOutlet weak var imageView: UIImageView!
        private var userID: String?
    
        func configure(id: String) {
            Firebase.User.observeSingle(id: id, type: .value) { [weak self] user in
                guard let `self` = self else { return }
                guard let user: Firebase.User = user else { return }
                if let profileImageRef = user.profileImage.ref {
                    imageView.load(profileImageRef) { self.userID == user.ID }
                }
            }
        }
    
        override func prepareForReuse() {
            super.prepareForReuse()
            userID = nil
            imageView.suspendLoading()
            imageView.image = nil
        }
    }
    

    여기까지 하면 비동기의 겹치는 TableViewCell 로의 이미지 로드로 낡은 이미지로 깜박이거나 하는 것은 없어집니다. 야터.

    이번에 구현한 라이브러리



    여기 에 있습니다
    pod 'ImageStore'
    

    사용하십시오.
    FirebaseStorage 는 Pod 의 dependency 에 넣을 수 없기 때문에 Example/ImageStore/ 아래에 있는 UIImageView+FirebaseStorage.swift ImageStore+FirebaseStorage.swift 를 프로젝트에 넣으면 행복해질 수 있습니다.
    그리고는 README.md 라고 이 기사를 읽으면 어쩐지 사용법을 알 수 있다고 생각합니다.
    또 버그등 있으면 꼭 issue나 PR 던져 주실 수 있으면 다행입니다.
  • 좋은 웹페이지 즐겨찾기