Заставьте Completionhandler работать в цикле For Fetching - PullRequest
0 голосов
/ 03 мая 2019

Я получаю пользовательские изображения из Firebase. Пользователь может иметь до 6 изображений, загруженных в базу данных. Я хочу загрузить изображения в CollectionView в правильном порядке (0-6).

Когда я пытаюсь использовать CompletionHandler, он не работает так, как я хочу. Перезагрузка CollectionView выполняется задолго до того, как изображения извлекаются, изображения не отображаются, потому что изображения помещаются в массив после вызова reloadData.

Буду признателен за помощь в этом вопросе.

Вот мой код:

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        downloadAndReload()
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return arrayImages.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "swipeCell", for: indexPath as IndexPath) as! ProfileCardCollectionViewCell
        let image = self.arrayImages[indexPath.item]
        cell.swipeProfileImage.image = image
        print("lägger ut cell")
        return cell
    }

    func downloadAndReload(){
        cachedImage(completion: { message in
            print(message)
            self.swipeCollectionView.reloadData()
        })
    }


    func cachedImage(completion: @escaping (_ message: String) -> Void){
        if let uid = Auth.auth().currentUser?.uid{
            for i in 0...6{

                let url = URL(string: uid+String(i))

                SDWebImageManager.shared.loadImage(with: url, options: .refreshCached, progress: .none ,completed: { (image, data, error, _, _, _) in

                    if let error = error{
                        print("Couldn't download image")
                        self.downloadImage(i: i, completion: {_ in

                        })
                    }
                    else{
                        print("Could download image")
                        self.arrayImages.append(image!)
                    }
                })
            }
            completion("DONE")
        }

    }

    func downloadImage(i: Int, completion: @escaping (_ fetchWorked: String) -> Void){
        print("Downloading Image")

        let g = DispatchGroup()
        g.enter()
        if let uid = Auth.auth().currentUser?.uid{
            let imagesStorageRef = Storage.storage().reference().child("profilepic/").child(uid+String(i))

            imagesStorageRef.downloadURL { url, error in
                guard let url = url else { return }

                SDWebImageManager.shared.loadImage(with: url, options: .refreshCached, progress: .none ,completed: { (image, data, error, _, _, _) in

                    if let error = error{
                    }
                    else{
                        self.arrayImages.append(image!)
                    }
                })

                g.leave()

            }
            g.notify(queue: .main, execute: {
                completion("Done")
            })
        }
    }

1 Ответ

0 голосов
/ 04 мая 2019

Дело в том, что у вас есть вложенные замыкания, поэтому, когда вы вызываете:

SDWebImageManager.shared.loadImage(with: url, options: .refreshCached, progress: .none ,completed: { (image, data, error, _, _, _) in

                if let error = error{
                    print("Couldn't download image")
                    self.downloadImage(i: i, completion: {_ in

                    })
                else{
                    print("Could download image")
                    self.arrayImages.append(image!)
                }
            })

Все внутри него будет вызываться только после завершения loadImage, поэтому ваше "for" будет вызывать "SDWebImageManager.shared.loadImage "6 раз, а затем вызвать" завершение ("Готово") ".

Таким образом, ваш код будет вызывать" завершение ("Готово") ", прежде чем он завершит обработку изображений, поэтому перезагружает данные, когда естьнет изображений или, возможно, пары.

Вам нужно подождать, пока загрузка завершится, прежде чем вызывать reloadData (), это будет зависеть от ваших потребностей, но вы можете просто получить изображения по мере необходимости, когда выЯ собираюсь установить изображения для содержимого ячейки, вызвать выборку изображений (сначала из кэша или загрузить, если они недоступны), а затем просто обновить, где они показаны.Таким образом, ваше приложение будет отображаться на экране более динамично, а также настраивать изображения-заполнители.

...