5

Im trying to create a collection view of images. I've tried these solutions, to download the images:
one
two
three
And
four

var tempObject = json["photos"]
                for var i = 0; i < tempObject.count; i++
                {
                    var tempImage = UIImage()

                    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {

                        tempImage =  UIImage(data: NSData(contentsOfURL: NSURL(string:"https://developer.apple.com/swift/images/swift-og.png")!)!)!
                    })

                    swiftImages.insert(tempImage, atIndex: i)
                }

                dispatch_async(dispatch_get_main_queue()) {

                    self.collectionView?.reloadData()
                }

But i can't get it to display the images. I'm new to networking with swift.

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! ImageCollectionViewCell
        cell.imageView.image = swiftImages[indexPath.row]
        return cell
    }
Community
  • 1
  • 1
Egghead
  • 6,837
  • 5
  • 20
  • 38

2 Answers2

2

you are adding UIImage() (the one created just before dispatch_async block) objects to swiftImages array. Please realize that dispatch_async block is executed sometime in future, It is not executed right after var tempImage = UIImage() line. Grab the image from inside dispatch block, also that's where you should fire the dispatch to main queue to reload collection. Change your code like this:

            var tempObject = json["photos"]
            for var i = 0; i < tempObject.count; i++
            {
                dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {

                    var tempImage =  UIImage(data: NSData(contentsOfURL: NSURL(string:"https://developer.apple.com/swift/images/swift-og.png")!)!)!
                    swiftImages.insert(tempImage, atIndex: i)
                    dispatch_async(dispatch_get_main_queue()) {

                       self.collectionView?.reloadData()
                    }
                })
            }

btw loading images for collection view or table view cells is not just about reading the images, you might some time by using something like AlamofireImage.

ishaq
  • 1,781
  • 1
  • 11
  • 19
  • 1
    Reloading the tableview every time you get a new image is not the smartest idea anyway – oiledCode Jan 26 '16 at 10:49
  • of course, but explaining all the good practices related to images in table and collection views would have been beyond the scope of this question. That's why I recommended AlamofireImage to get him started. – ishaq Jan 26 '16 at 10:50
  • Thanks used AlamofireImage – Egghead Jan 26 '16 at 20:27
0

There's a problem in this code:

                var tempImage = UIImage()

                dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {

                    tempImage =  UIImage(data: NSData(contentsOfURL: NSURL(string:"https://developer.apple.com/swift/images/swift-og.png")!)!)!
                })

                swiftImages.insert(tempImage, atIndex: i)

tempImage is always empty because the downloading is asynchronous and you insert it to swiftImages before the downloading is finished.

I would recommend you to use some library like SDWebImage. You don't have to do the downloading manually. It's super simple to use it and you get all the networking for free:

import SDWebImage

let imageView = UIImageView()
imageView.sd_setImageWithURL( ... url ... )
VojtaStavik
  • 2,312
  • 1
  • 18
  • 30
  • 1
    isn't SDWebImage Objective C based? If someone's starting with a Swift app, I think it's best to stay with as many pure Swift libs as possible, AlamofireImage nicely fills image loading requirements. (don't get me wrong, I love SDWebImage for Objective C projects). – ishaq Jan 26 '16 at 10:54
  • Yeah, that's an interesting point. Sure, it really doesn't matter which one to use, when you're using them as embedded frameworks. You don't feel the difference... – VojtaStavik Jan 26 '16 at 11:08
  • You are right from API consumer standpoint. iI you are debugging though, and single stepping through code that calls into embedded framework code, a pure swift framework means you don't have to brain-switch from Swift to objective C syntax. Makes it a bit easier to find issues. – ishaq Jan 26 '16 at 11:15