Charger des images à partir d'URL et ScrollView

Bonjour à tous,
J'ai mis en place une vue avec un scrollView horizontal afin d'afficher toutes les images que je récupère à partir d'une API.
Voici en gros le code (ne pas faire attention aux !, je les enlèverai à la fin :smile: )
j'ai mis en commentaire ce qui pose problème actuellement (chargement trop long), j'ai chargé une image à partir d'un fichier en locale

        for i in 0 ..< self.imgArray.count
            {

                    /*
                    let str1 = (self.imgArray.object(at: i) as AnyObject).value(forKey: "imageURL") as! String
                    let strURL1 = str1.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)

                    let original = strURL1
                    let urlString = original.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlFragmentAllowed)

                    let urlPhoto = URL(string: urlString!)

                    let data1 = try? Data(contentsOf: urlPhoto!) 

                    pageImages.append(UIImage(data: data1!)!)
                    */

                    if let image = UIImage(named: "picture.png") {

                        self.pageImages.append(image)

                    }


            }



            let wBounds = self.view.bounds.width
            let hBounds = self.view.bounds.height


            self.scrollView = UIScrollView()
            self.scrollView.backgroundColor = UIColor.clear
            self.scrollView.frame = self.view.frame
            self.scrollView.isPagingEnabled = true
            self.scrollView.showsHorizontalScrollIndicator = false
            self.scrollView.delegate = self
            self.scrollView.bounces = false

            self.scrollView.minimumZoomScale = 1.0
            self.scrollView.maximumZoomScale = 2.0

            self.view.addSubview(self.scrollView)

            self.scrollView.contentSize = CGSize(width: self.view.bounds.size.width * CGFloat(self.pCount), height: hBounds/2)



            self.pageControl = UIPageControl()
            self.pageControl.frame = CGRect(x: self.view.frame.width/2, y: self.view.frame.height-20, width: 0, height: 0)
            self.pageControl.backgroundColor = UIColor.white
            self.pageControl.numberOfPages = self.pCount
            self.pageControl.currentPage = 0
            self.pageControl.currentPageIndicatorTintColor = UIColor(red:0.325, green:0.667, blue:0.922, alpha: 1)
            self.pageControl.pageIndicatorTintColor = UIColor.white
            self.view.addSubview(self.pageControl)


            for i in 0..<self.imgArray
            {
                self.view1 = UIView()

                self.view1.frame = CGRect(x: 0, y: 0, width: wBounds, height: hBounds)
                self.newPageView1 = UIImageView(image: self.pageImages[i])
                self.newPageView1.contentMode = .scaleAspectFit

                self.newPageView1.frame = CGRect(x: wBounds * CGFloat(i), y: 0, width: wBounds, height: hBounds)
                self.view1.addSubview(self.newPageView1)
                self.scrollView.addSubview(self.view1)
                self.scrollView.bringSubviewToFront(self.view1)
            }

Je souhaiterais que les images se chargent au fur et à mesure que je scrolle, actuellement tout se charge la première fois que j'accède à la vue, c'est donc trop long.
Merci de votre aide.

Réponses

  • let data1 = try? Data(contentsOf: urlPhoto!) : Ceci est synchone et bloque le thread courant.
    Il faut utiliser URLSession, ou je recommanderai même d'utiliser SDWebImage, KingFisher, AlamofireImage, AFNetworkingImage plutôt.

    Je recommanderai également d'utiliser une UICollectionView. Pourquoi ? Actuellement, tu charges tout. Tu es obligé d'avoir TOUT en mémoire. Alors qu'en réalité, seul ce qui apparaît à l'écran devrait être chargé. L'UICollectionView est faite pour ça et est optimisée (avec le reuse). Tu peux faire du préchargement sur une UICollectionView (c'est dispo en publique depuis iOS9 ou 10, avant il fallait le faire manuellement). De plus, les code tiers cité précédemment gèrent également le cache, donc il ne retéléchargent pas à chaque fois l'image.

  • @Larme a dit :

    Je recommanderai également d'utiliser une UICollectionView. Pourquoi ? Actuellement, tu charges tout. Tu es obligé d'avoir TOUT en mémoire. Alors qu'en réalité, seul ce qui apparaît à l'écran devrait être chargé. L'UICollectionView est faite pour ça et est optimisée (avec le reuse). Tu peux faire du préchargement sur une UICollectionView (c'est dispo en publique depuis iOS9 ou 10, avant il fallait le faire manuellement). De plus, les code tiers cité précédemment gèrent également le cache, donc il ne retéléchargent pas à chaque fois l'image.

    J'allais répondre à peu prés la même chose. Utiliser une scrollView est une mauvaise idée. Il est préférable de passer par d'autres contrôles (collectionView ou pageView) dérivant de scrollView, mais offrant un meilleur contrôle sur le chargement/déchargement du contenu. Une collectionView est une scrollView intelligente n'affichant que le contenu visible sur l'écran.

  • Merci pour les conseils.

  • @Larme a dit :
    Je recommanderai également d'utiliser une UICollectionView.

    Tu peux arriver à la même finalité avec un UITableView, non ?

  • @Jérémy a dit :
    Tu peux arriver à la même finalité avec un UITableView, non ?

    Absolument. D'ailleurs le sommaire de l'application de la revue LePoint est réalisé avec une tableView. Les titres des articles sont chargés en une seule fois, alors que les images sont téléchargées au fur et à mesure des besoins.

  • Parfait ! :)

    Je ne connaissais pas AlamofireImage. Je viens de jeter un oeil, c'est top ! ;)

  • @Jérémy a dit :

    @Larme a dit :
    Je recommanderai également d'utiliser une UICollectionView.

    Tu peux arriver à la même finalité avec un UITableView, non ?

    Sa demande portait sur un scroll view horizontal, du coup l'idée du TableView tombe à l'eau.

    Faire avec un ScrollView est totalement possible mais je rejoins @Larme sur l'utilisation du CollectionView beaucoup plus adapté tout comme l'utilisation de URL Session et NSCache ou via une librairie.

Connectez-vous ou Inscrivez-vous pour répondre.