загрузка изображений viewview коллекции после загрузки viewcontroller - PullRequest
0 голосов
/ 03 мая 2020

Итак, я быстро создаю приложение, в котором пользователь может загрузить продукт с изображениями. Загрузка работает отлично, но у меня проблема с загрузкой картинок. Пользователь получает обзор всех продуктов и нажимает на них, а затем отправляет ему подробный обзор этого продукта. В этом обзоре есть представление коллекции со всеми изображениями (это цель). Моя проблема в том, что картинка загружается слишком медленно для просмотра коллекции и не появляется на экране. Мне было интересно, есть ли возможность дать представление изображения в функции и назначить изображения для них, и что изображения будут загружаться одна за другой после того, как экран уже загрузился?

Это функция, которая у меня сейчас есть для загрузки моих изображений:

    func getPictures(imageStrings: [String], imageViews: [UIImageView]){
        let storage = Storage.storage();
        for index in 0...imageStrings.count - 1 {
            let gsReference = storage.reference(forURL: imageStrings[index])
            gsReference.getData(maxSize: 15 * 1024 * 1024) { data, error in
                    if let error = error {
                            // Uh-oh, an error occurred!
                            print(error)
                            return
                    } else {
                        DispatchQueue.main.async {
                        imageViews[index].image = UIImage(data: data!)
                        }
                        print(UIImage(data: data!) as Any)
                    }
            }
        }
    }

это контроллер вида, где мой просмотр коллекции активен

import MessageUI
import FirebaseStorage

class ProductDetailViewController: UIViewController, MFMailComposeViewControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource   {


    @IBOutlet var TitleLable: UILabel!
    @IBOutlet var PriceLable: UILabel!
    @IBOutlet var ProductDate: UILabel!
    @IBOutlet var UsernameLable: UILabel!
    @IBOutlet var LocationLable: UILabel!
    @IBOutlet var Userdate: UILabel!
    @IBOutlet var ReserveerButton: UIButton!
    @IBOutlet var DescriptionTextView: UITextView!
    @IBOutlet var collectionView: UICollectionView!

    var titleLable = String()
    var priceLable = String()
    var productDate = String()
    var descriptionLable = String()
    var userId = String()
    var usernameLable = String()
    var locationLable = String()
    var userdate = String()
    var email = String()
    var imageStrings = [String]()
    var images = [UIImage]()
    var dbhelper = DBHelper()

    override func viewDidLoad() {
        super.viewDidLoad()
        ReserveerButton.layer.cornerRadius = 20
        loadUser(id: userId)
        TitleLable.text = titleLable
        PriceLable.text = priceLable
        ProductDate.text = productDate
        DescriptionTextView.text = descriptionLable
        UsernameLable.text = usernameLable
        loadImages()    

        // Do any additional setup after loading the view.
    }

    private func loadUser(id: String){
        let dbhelper = DBHelper()
        dbhelper.getUserbyUserID(id: id){ success in
            if(dbhelper.users[0].Bedrijf != "NULL"){
                self.UsernameLable.text = dbhelper.users[0].Bedrijf
            } else {
                self.UsernameLable.text = dbhelper.users[0].Voornaam + " " + dbhelper.users[0].Familienaam
            }
            self.Userdate.text = dbhelper.users[0].Added_on
            self.LocationLable.text = dbhelper.users[0].Stad
            self.email = dbhelper.users[0].Email
        }
    }

    @IBAction func ReserveerProduct(_ sender: Any) {
        if !MFMailComposeViewController.canSendMail() {
            print("Mail services are not available")
            return
        }

        let composeVC = MFMailComposeViewController()
        composeVC.mailComposeDelegate = self

        // Configure the fields of the interface.
        composeVC.setToRecipients([self.email])
        composeVC.setSubject(self.titleLable)
        composeVC.setMessageBody("Beste " + self.usernameLable + ", \n\nIk zou graag het zoekertje " + self.titleLable + " reserveren.  Is dit nog steeds mogelijk? \n\nMet vriendelijke groet" , isHTML: false)

        // Present the view controller modally.
        self.present(composeVC, animated: true, completion: nil)

    }

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {

        switch result.rawValue {
        case MFMailComposeResult.cancelled.rawValue :
            print("Cancelled")

        case MFMailComposeResult.failed.rawValue :
            print("Failed")

        case MFMailComposeResult.saved.rawValue :
            print("Saved")

        case MFMailComposeResult.sent.rawValue :
            print("Sent")
        default: break
        }
        self.dismiss(animated: true, completion: nil)
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
        cell.contentMode = .scaleAspectFill
        return cell
    }

    func loadImages(){
        let dbhelper = DBHelper()
        //dbhelper.getPictures2(imageStrings: self.imageStrings, imageViews: self.images)
    }

}

Надеюсь Я наконец могу решить эту проблему! С уважением, Б.

1 Ответ

1 голос
/ 03 мая 2020

Полагаю, проблема в том, что вы не обновляете представление коллекции после загрузки изображений.

Во-первых, ваш getPictures(...) метод ожидает массив UIImageViews. Но на самом деле вы не можете передать их методу, потому что они динамически создаются в вашем collectionView. Вместо этого вы должны вернуть изображения, как только они загружены. Проблема в том, что изображения загружаются асинхронно. Это означает, что вам нужно использовать обработчик завершения.

func getPictures(imageStrings: [String], completionHandler: @escaping (UIImage) -> ()) {
    let storage = Storage.storage();
    for index in 0...imageStrings.count - 1 {
        let gsReference = storage.reference(forURL: imageStrings[index])
        gsReference.getData(maxSize: 15 * 1024 * 1024) { data, error in
                if let error = error {
                        // Uh-oh, an error occurred!
                        print(error)
                        return
                } else {
                    completionHandler(UIImage(data: data!))
                    print(UIImage(data: data!) as Any)
                }
        }
    }
}

Затем вам нужно изменить метод loadImages():

    func loadImages() {
        let dbhelper = DBHelper()
        dbhelpergetPictures(imageStrings: [""]) { (loadedImage) in
            DispatchQueue.main.async {
                self.images.append(loadedImage)
                self.collectionView.reloadData()
            }
        }
    }

После этого вам необходимо изменить свой collectionView (numberOfItemsInSection ) метод, чтобы сделать количество отображаемых ячеек равным количеству загруженных изображений:

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

И, наконец, вам нужно фактически отобразить изображения в UIImageViews внутри представления вашей коллекции:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
    cell.contentMode = .scaleAspectFill
    cell.imageView.image = images[indexPath.row]
    return cell
}

Если у вас есть какие-либо вопросы по этому поводу, просто задавайте их в комментариях.

(PS: совет из лучших побуждений: взгляните на быстрые соглашения об именах ( здесь Руководство по стилю ). Все имена, кроме классов, всегда должны начинаться со строчной буквы и описывать их назначение. Пример: var TitleLable: UILabel! -> var titleLable: UILabel! и: var titleLable = String() -> var title = String() Это будет сделайте ваш код более понятным!)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...