集合视图单元格没有出现在集合视图中?

Posted

技术标签:

【中文标题】集合视图单元格没有出现在集合视图中?【英文标题】:Collection views cells are not appearing in collection view? 【发布时间】:2015-11-01 01:36:49 【问题描述】:

这是我第一次使用集合视图,我很挣扎。我在“setupView”函数中设置了一个集合视图布局,然后实现了典型的视图方法,比如 numberOfSections 和 cellForRowAtIndexPath。现在,我只是想让集合视图正常工作,所以我只是使用工作区中已有的图像,而不是从 API 获取图片(稍后会出现)。

这是我正在使用的代码。为什么除了黑屏什么都不显示?

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

这是我的 setupView 函数。

   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)

情节提要中的一切看起来都一团糟。我正在使用 UICollectionViewController swift 类(不是 UIViewController + collectionView 组合),我真的不知道应该使用哪些插座。这是我在整个视图控制器上的连接列表:

最后,这是我非常简单的视图层次结构。

我真的不知道为什么集合视图不能正常工作。有什么想法吗?

编辑 1:我更改了很多代码并最终让我的 collectionView 工作。对于那些在类似问题上苦苦挣扎的人,这里是我用于 collectionView 的全部代码。也许它会帮助你解决你自己的collectionView代码中的问题

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()



【问题讨论】:

在设置后再次尝试在 UIcollectionview 上调用 reloadData。 【参考方案1】:

数据格式化后,只需重新加载您的 collectionView。 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()

【讨论】:

我非常非常困惑的一件事是我应该使用picturesCollectionView 还是collectionView。我的理解是,当您创建我拥有的集合视图控制器时,Xcode 会自动“设置”collectionView,因此我可以直接访问该collectionView 变量。但是由于我已经为我的 collectionView 创建了一个到 collection view 控制器的出口,称为“picturesCollectionView”,我应该使用 picturesCollectionView 还是直接使用提供的 collectionView 变量? picturesCollectionView.reloadData() 或 collectionView.reloadData() 都有效。 collectionView 是你的 UICollectionViewController 的一个实例,而 picturesColectionView 也是你的 UICollectionViewController 控制器的一个实例。唯一的区别是picturesCollectionView 是你的UICollectionViewController 的一个IBOutlet。 好吧,很高兴知道它们之间没有任何真正的区别。 我想我不小心删除了你最后的评论凯。我在代码中更改了很多东西并将解决方案代码发布为编辑。

以上是关于集合视图单元格没有出现在集合视图中?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 中的集合视图单元格动画

集合视图单元格上的重叠阴影

以编程方式将按钮添加到集合视图单元格

在集合视图中有包含数据的单元格和空单元格

如何更改集合视图锡约束中单元格的位置?

在集合单元格中添加背景视图