Jack Berstrem
Jack Berstrem

Reputation: 535

Collection views cells are not appearing in collection view?

This is my first time working with collection views and I am struggling quite a bit. I set up a collection view layout in the "setupView" function, and then implemented the typical view methods, like numberOfSections and cellForRowAtIndexPath. Right now, I'm just trying to get the collection view to work so I'm just using an image that I already have in my workspace, instead of getting pictures from an API (that will come later).

Here is the code I am using. Why is it not displaying anything other than a black screen ?

import UIKit
import Alamofire
import AlamofireImage

class PhotoBrowserCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

let goldenWordsYellow = UIColor(red: 247.00/255.0, green: 192.00/255.0, blue: 51.00/255.0, alpha: 0.5)

@IBOutlet weak var menuButton:UIBarButtonItem!

@IBOutlet var picturesCollectionView: UICollectionView!

var pictureObjects = NSMutableOrderedSet(capacity: 1000)

var customRefreshControl = UIRefreshControl()

let PhotoBrowserCellIdentifier = "PhotoBrowserCell"

var dateFormatter = NSDateFormatter()

var nodeIDArray = NSMutableArray()

var timeStampDateString : String!

override func viewDidLoad() {
    super.viewDidLoad()

    self.collectionView!.registerClass(PhotoBrowserCollectionViewCell.self, forCellWithReuseIdentifier: PhotoBrowserCellIdentifier)

    self.revealViewController().rearViewRevealWidth = 280

    collectionView!.delegate = self
    collectionView!.dataSource = self

    customRefreshControl = UIRefreshControl()
    customRefreshControl.backgroundColor = goldenWordsYellow
    customRefreshControl.tintColor = UIColor.whiteColor()
    self.picturesCollectionView!.addSubview(customRefreshControl)

    navigationController?.setNavigationBarHidden(false, animated: true)
    navigationItem.title = "Pictures"


    setupView()

    populatePhotos()

    self.dateFormatter.dateFormat = "dd/MM/yy"

}


override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 5 // setting an arbitrary value in case pictureObjects is not getting correctly populated
}

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(PhotoBrowserCellIdentifier, forIndexPath: indexPath) as! PhotoBrowserCollectionViewCell

    cell.imageView.image = UIImage(named: "mail")

    return cell
}

And here is my setupView function.

   override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    performSegueWithIdentifier("ShowPhoto", sender: (self.pictureObjects.objectAtIndex(indexPath.item) as! PictureElement).imageURL)
}

func setupView() {
    navigationController?.setNavigationBarHidden(false, animated: true)

    let layout = UICollectionViewFlowLayout()
    let itemWidth = (view.bounds.size.width - 2) / 3
    layout.itemSize = CGSize(width: itemWidth, height: itemWidth)
    layout.minimumInteritemSpacing = 1.0
    layout.minimumLineSpacing = 1.0

    collectionView!.collectionViewLayout = layout

    navigationItem.title = "Pictures"

    customRefreshControl.tintColor = UIColor.whiteColor()
    customRefreshControl.addTarget(self, action: "handleRefresh", forControlEvents: .ValueChanged)
    self.collectionView!.addSubview(customRefreshControl)
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSizeMake(120, 120)
}

Everything looks really messed up in the storyboard. I'm using a UICollectionViewController swift class (not a UIViewController + collectionView combo), and I don't really know which outlets I should be using. Here is my list of connections on the entire view controller:

Connections

And finally, here is my very simple view hierarchy.

I truly have no idea why the collection view isn't working properly. Any ideas ?

EDIT 1: I changed a lot of code and ended up getting my collectionView to work. For those who are struggling with a similar issue, here is the entirety of the code I am using for the collectionView. Maybe it will help you fix problems in your own collectionView code

import UIKit
import Alamofire
import AlamofireImage

class PhotoBrowserCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

let goldenWordsYellow = UIColor(red: 247.00/255.0, green: 192.00/255.0, blue: 51.00/255.0, alpha: 0.5)

@IBOutlet weak var menuButton:UIBarButtonItem!

@IBOutlet var picturesCollectionView: UICollectionView!

var temporaryPictureObjects = NSMutableOrderedSet(capacity: 1000)
var pictureObjects = NSMutableOrderedSet(capacity: 1000)

var goldenWordsRefreshControl = UIRefreshControl()

var revealViewControllerIndicator : Int = 0

let imageCache = NSCache()

var customView: UIView!

var labelsArray: [UILabel] = []

var isAnimating = false

var currentColorIndex = 0

var currentLabelIndex = 0

var timer : NSTimer!

var populatingPhotos = false

var currentPage = 0

let PhotoBrowserCellIdentifier = "PhotoBrowserCell"

var dateFormatter = NSDateFormatter()

var nodeIDArray = NSMutableArray()

var timeStampDateString : String!

var cellLoadingIndicator = UIActivityIndicatorView()

var scrollViewDidScrollLoadingIndicator = UIActivityIndicatorView()

override func viewDidLoad() {
    super.viewDidLoad()

    self.collectionView!.registerClass(PhotoBrowserCollectionViewCell.self, forCellWithReuseIdentifier: PhotoBrowserCellIdentifier)

    self.cellLoadingIndicator.backgroundColor = goldenWordsYellow
    self.cellLoadingIndicator.hidesWhenStopped = true

if self.revealViewController() != nil {
    revealViewControllerIndicator = 1
    menuButton.target = self.revealViewController()
    menuButton.action = "revealToggle:"
    self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }

    self.revealViewController().rearViewRevealWidth = 280

    collectionView!.delegate = self
    collectionView!.dataSource = self

    goldenWordsRefreshControl = UIRefreshControl()
    goldenWordsRefreshControl.backgroundColor = goldenWordsYellow
    goldenWordsRefreshControl.tintColor = UIColor.whiteColor()
    self.collectionView!.addSubview(goldenWordsRefreshControl)

    navigationController?.setNavigationBarHidden(false, animated: true)
    navigationItem.title = "Pictures"

    setupView()

    populatePhotos()

    self.dateFormatter.dateFormat = "dd/MM/yy"

    self.cellLoadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
    self.cellLoadingIndicator.color = goldenWordsYellow
    self.cellLoadingIndicator.center = (self.collectionView?.center)!
    self.collectionView!.addSubview(cellLoadingIndicator)
    self.collectionView!.bringSubviewToFront(cellLoadingIndicator)


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

override func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    if goldenWordsRefreshControl.refreshing {
        if !isAnimating {
            holdRefreshControl()
        }
    }
}

func holdRefreshControl() {
    timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "handleRefresh", userInfo: nil, repeats: true)
}

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return (pictureObjects.count) // setting an arbitrary value in case pictureObjects is not getting correctly populated
}

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(PhotoBrowserCellIdentifier, forIndexPath: indexPath) as! PhotoBrowserCollectionViewCell

    if let pictureObject = pictureObjects.objectAtIndex(indexPath.row) as? PictureElement {

        let title = pictureObject.title ?? "" // if pictureObject.title == nil, then we return an empty string

        let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(pictureObject.timeStamp))
        let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)

        let author = pictureObject.author ?? ""

        let issueNumber = pictureObject.issueNumber ?? ""
        let volumeNumber = pictureObject.volumeNumber ?? ""

        let nodeID = pictureObject.nodeID ?? 0

        let imageURL = pictureObject.imageURL ?? "http://goldenwords.ca/sites/all/themes/custom/gw/logo.png"

        cell.request?.cancel()

        if let image = self.imageCache.objectForKey(imageURL) as? UIImage {

            cell.imageView.image = image

        } else {

            cell.imageView.image = nil
            cell.request = Alamofire.request(.GET, imageURL).responseImage() { response in
                if let image = response.result.value {

                    self.imageCache.setObject(response.result.value!, forKey: imageURL)
                    if cell.imageView.image == nil {
                        cell.imageView.image = image
                    }
                }
            }
        }
    }

    return cell
}




    self.performSegueWithIdentifier("ShowPhoto", sender: self)
}

func setupView() {
    navigationController?.setNavigationBarHidden(false, animated: true)

    let layout = UICollectionViewFlowLayout()
    let itemWidth = (view.bounds.size.width) / 3
    layout.itemSize = CGSize(width: itemWidth, height: itemWidth)
    layout.minimumInteritemSpacing = 1.0
    layout.minimumLineSpacing = 1.0

    collectionView!.collectionViewLayout = layout

    navigationItem.title = "Pictures"

}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSizeMake(((self.collectionView?.frame.width)!*0.5)-2, self.collectionView!.frame.height/3)
}




override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "ShowPhoto" {

        let detailViewController = segue.destinationViewController as! PhotoViewerViewController
        let indexPaths = self.collectionView!.indexPathsForSelectedItems()
        let indexPath = indexPaths![0] as! NSIndexPath

        let item = indexPath.item

    }
}

override func scrollViewDidScroll(scrollView: UIScrollView) {
    if (scrollView.contentOffset.y + view.frame.size.height > scrollView.contentSize.height * 0.75) {
        populatePhotos()
    }
}

func populatePhotos() {

    if populatingPhotos {
        return
    }
    populatingPhotos = true

    self.cellLoadingIndicator.startAnimating()
    self.temporaryPictureObjects.removeAllObjects()

    Alamofire.request(GWNetworking.Router.Pictures(self.currentPage)).responseJSON() { response in
        if let JSON = response.result.value {

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)) {

            var nodeIDArray : [Int]

            if (JSON .isKindOfClass(NSDictionary)) {

                for node in JSON as! Dictionary<String, AnyObject> {

                    let nodeIDValue = node.0
                    var lastItem : Int = 0

                    self.nodeIDArray.addObject(nodeIDValue)

                    if let pictureElement : PictureElement = PictureElement(title: "Picture", nodeID: 0, timeStamp: 0, imageURL: "http://goldenwords.ca/sites/all/themes/custom/gw/logo.png", author: "Staff", issueNumber: "Issue # error", volumeNumber: "Volume # error") {

                        pictureElement.title = node.1["title"] as! String
                        pictureElement.nodeID = Int(nodeIDValue)!

                        let timeStampString = node.1["revision_timestamp"] as! String
                        pictureElement.timeStamp = Int(timeStampString)!

                        if let imageURL = node.1["image_url"] as? String {
                            pictureElement.imageURL = imageURL
                        }

                        if let author = node.1["author"] as? String {
                            pictureElement.author = author
                        }

                        if let issueNumber = node.1["issue_int"] as? String {
                            pictureElement.issueNumber = issueNumber
                        }

                        if let volumeNumber = node.1["volume_int"] as? String {
                            pictureElement.volumeNumber = volumeNumber
                        }

                        if self.pictureObjects.containsObject(pictureElement) {
                            // do not add the pictureElement to the set of pictures
                        } else {
                        lastItem = self.temporaryPictureObjects.count // Using a temporary set to not handle the dataSource set directly (safer).
                        self.temporaryPictureObjects.addObject(pictureElement)
                        }

                        let indexPaths = (lastItem..<self.temporaryPictureObjects.count).map { NSIndexPath(forItem: $0, inSection: 0) }
                    }

                }

                let timeStampSortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: false)
                self.temporaryPictureObjects.sortUsingDescriptors([timeStampSortDescriptor])

            }
            dispatch_async(dispatch_get_main_queue()) {

                for object in self.temporaryPictureObjects {
                    self.pictureObjects.addObject(object)
                }

                self.temporaryPictureObjects.removeAllObjects()

                self.collectionView!.reloadData()
                self.cellLoadingIndicator.stopAnimating()
                self.goldenWordsRefreshControl.endRefreshing()

                self.currentPage++
                self.populatingPhotos = false
            }
        }
    }
}
}



func handleRefresh() {

    goldenWordsRefreshControl.beginRefreshing()

    self.pictureObjects.removeAllObjects()
    self.temporaryPictureObjects.removeAllObjects()

    self.collectionView!.reloadData()

    self.currentPage = 0

    self.picturesCollectionView.bringSubviewToFront(cellLoadingIndicator)

    self.populatingPhotos = false
    populatePhotos()

}
}

Upvotes: 1

Views: 2497

Answers (1)

kye
kye

Reputation: 2246

Simply reload your collectionView after the data is formatted. picturesCollectionView.reloadData()

override func viewDidLoad() {
    super.viewDidLoad()

    self.collectionView!.registerClass(PhotoBrowserCollectionViewCell.self, forCellWithReuseIdentifier: PhotoBrowserCellIdentifier)

    self.revealViewController().rearViewRevealWidth = 280

    collectionView!.delegate = self
    collectionView!.dataSource = self

    customRefreshControl = UIRefreshControl()
    customRefreshControl.backgroundColor = goldenWordsYellow
    customRefreshControl.tintColor = UIColor.whiteColor()
    self.picturesCollectionView!.addSubview(customRefreshControl)

    navigationController?.setNavigationBarHidden(false, animated: true)
    navigationItem.title = "Pictures"


    setupView()

    populatePhotos()

    self.dateFormatter.dateFormat = "dd/MM/yy"
    picturesCollectionView.reloadData()
}

Upvotes: 1

Related Questions