在UITableView原型中带有Images的UICollectionView单元格 [英] UICollectionView cells with Images inside UITableView prototype

查看:103
本文介绍了在UITableView原型中带有Images的UICollectionView单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:我解决了直到在collectionView上滚动才加载正确图像的主要问题。我在tableView:cellForRowAtIndexPath中添加了一个collectionView.reloadData()。我还做了一些更改来预加载序列数组,而不是在滚动表时构建它(tableView:cellForRowAtIndexPath)。



如果你添加了GitHub的更新感兴趣。

听到希望这给了更多详细解释比这篇文章。


UPDATE: I solved my primary issue of correct images not loading until scrolling on the collectionView. I added a collectionView.reloadData() to the tableView:cellForRowAtIndexPath. I also made some changes to pre-load the sequence array, instead of building it while scrolling through the table (tableView:cellForRowAtIndexPath).

Added the updates to GitHub if you are interested.
https://github.com/Druiced/OpenDeck

I will follow-up once I figure out how to prevent the App from crashing when a dynamic value is placed in the return (if i set this to 15, the app will not crash):

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return count(Array(sequenceArray[collectionView.tag])) / 2
}

ORIGINAL POST: request for some guidance.

This tutorial helped me realize this must have to do with my DataSource/Delegate. The author builds the cell with addSubview instead of taking advantage of the Xcode prototype cell, which seems like a cool thing, so I'm trying to do it. http://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell

Any criticism about my approach or failure to follow best practices is welcome.

Each cell in the table has a UICollectionView. Each cell in the Collection View displays an image in order of the saved "Sequence" string. example: "ADKDQDJDTD" link up to AD.png KD.png QD.png JD.png TD.png

I have two issues I can't seem to get past.

  • numberOfItemsInSection gets whacky when the number of cards is driven by the array length (return handArray.count / 2). If I place a fixed number the app will work, but not very slick.
  • When the table first comes up, the correct cards do not display until I scroll up and down the table. It also appears the data for each CollectionView is crossing paths as the wrong cards show up when scrolling up and down rapidly.

I'm almost positive this has to do with how my datasource is setup.

DeckTableViewController.swift

import UIKit
import Parse

var deviceID: String?
var noRefresh: Bool?
var sequenceArray: Array<Character>?

class DeckTableViewController: UITableViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var handArray: Array<Character>!
var timeLineData:NSMutableArray = NSMutableArray()

override func viewDidLoad() {
    super.viewDidLoad()
    noRefresh = false
    deviceId = UIDevice.currentDevice().identifierForVendor.UUIDString
}

override func viewDidAppear(animated: Bool) {
    if noRefresh == false {
        loadData()
        noRefresh = true
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return timeLineData.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell:DeckTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! DeckTableViewCell

    let deck:PFObject = timeLineData.objectAtIndex(indexPath.row) as! PFObject

    cell.collectionView.dataSource = self
    cell.collectionView.delegate = self

    let sequenceTemp = deck.objectForKey("Sequence") as! String
    handArray = Array(sequenceTemp)
    cell.sequenceId.setTitle(deck.objectId, forState: UIControlState.Normal)
    cell.cardCountLabel.text = "\((count(sequenceTemp)/2))"

    // Date to String Stuff
    var dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "(MM-dd) hh:mm:ss"
    cell.timeLabel.text = dateFormatter.stringFromDate(deck.updatedAt!)

    let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    layout.itemSize = CGSizeMake(99, 140)
    layout.scrollDirection = UICollectionViewScrollDirection.Horizontal

    cell.collectionView.collectionViewLayout = layout

    return cell
}


func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return handArray.count / 2
}

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

    let cell:TableCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! TableCollectionViewCell
    var bcolor : UIColor = UIColor.orangeColor()
    cell.layer.borderColor = bcolor.CGColor
    cell.layer.borderWidth = 2
    cell.layer.cornerRadius = 3

    var firstLetter: Character!
    var secondLetter: Character!

    //Building card file names from Sequence data
    if (indexPath.row * 2) + 1 <= handArray.count {

        firstLetter = handArray[indexPath.row * 2]
        secondLetter = handArray[indexPath.row * 2 + 1]
        let imageNameString = "\(firstLetter)\(secondLetter).png"
        let front = UIImage(named: imageNameString)
        cell.ImageView.backgroundColor = UIColor.orangeColor()
        cell.ImageView.image = front

    }

    return cell
}

DeckTableViewCell.swift

import UIKit

class DeckTableViewCell: UITableViewCell, UITextViewDelegate {

    @IBOutlet var collectionView: UICollectionView!
    @IBOutlet var sequenceId: UIButton!
    @IBOutlet var timeLabel: UILabel!
    @IBOutlet var cardCountLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

    }
}

TableCollectionViewCell.swift

import UIKit

class TableCollectionViewCell: UICollectionViewCell {

    @IBOutlet var ImageView: UIImageView!

}

For this example I set (return handArray.count / 2) to a 10 and loaded 3 sequences. The number in the top center represents the number of cards for each row. Notice the CollectionView does not update with the right cards, it's picking up data from the other CollectionViews. IF I add bunch more sequences to this mix, when scrolling up and down, the correct cards WILL populate SOMETIMES, but unpredictable.

Thanks for any suggestions, I'm happy to go back to the drawing board. Cheers

解决方案

Ok lets think this way, your DeckTableViewController acts as datasource for tableview, and DeckTableViewCell acts as datasource for collection view.

with the above thing in mind we create a sample project i am not going in depth, i am giving example like the tutorial as u go through

lets create a sample project with single view app and in ViewController past the below code, i took one array of integers which contains some values as how many cells to be appears in collection view. don't forget add tableview and set its datasource and deleagte.

before we are coding to controller class we need some classes like custom tableview cell and custom collection view cell we create them first

create a new file which is the subclass of UICollectionViewCell and name it as CustomCollectionViewCell and with xib file.

class CustomCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var aLabel: UILabel!  //to show the card number
@IBOutlet weak var imageView: UIImageView! //imageview i am setting it's background color
override init(frame: CGRect) {
    super.init(frame: frame)

}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func awakeFromNib() {
    super.awakeFromNib()

    }
}

and create a outlets for label and image view as in the above code.

Next, create new file subclass of UITableViewCell and name it as CustomTableViewCell with xib file. open up CustomTableViewCell.xib file and drag and drop the collection view and set it's datasource and delegate to cell not the controller.

and create a outlet for the collection view and name it as foldersCollectionView. pass the below code

import UIKit

class CustomTableViewCell: UITableViewCell,UICollectionViewDataSource,UICollectionViewDelegate {

@IBOutlet weak var foldersCollectionView: UICollectionView!

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init(coder aDecoder: NSCoder) {
   // fatalError("init(coder:) has not been implemented")
    super.init(coder: aDecoder)
}

var folderCount:Int?
{
    didSet(value)
    {

    }
}


override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
    //configure our collectionview
    var aFlowLayout : UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    aFlowLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal
    aFlowLayout.itemSize = CGSizeMake(60.0, 90.0)
    aFlowLayout.minimumLineSpacing = 10.0
    aFlowLayout.minimumInteritemSpacing = 0.0
    aFlowLayout.sectionInset = UIEdgeInsetsMake(2, 9, 0, 10)
    foldersCollectionView.collectionViewLayout = aFlowLayout
    foldersCollectionView.registerClass(CustomCollectionViewCell.self, forCellWithReuseIdentifier: "FOLDER_CELL")
    var cNib:UINib? = UINib(nibName: "CustomCollectionViewCell", bundle: nil)
    foldersCollectionView.registerNib(cNib, forCellWithReuseIdentifier: "FOLDER_CELL")
    foldersCollectionView.frame = self.bounds
}


override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

class func CreateCustomCell() -> CustomTableViewCell
{
    var nibElements: Array = NSBundle.mainBundle().loadNibNamed("CustomTableViewCell", owner: self, options: nil)
    var item: AnyObject?
    for item in nibElements
    {
        if item is UITableViewCell
        {
            return item as CustomTableViewCell
        }
    }
    return item as CustomTableViewCell
}


func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    var cell :CustomCollectionViewCell? = collectionView.dequeueReusableCellWithReuseIdentifier("FOLDER_CELL", forIndexPath: indexPath) as? CustomCollectionViewCell
    //hear u can modify which image to be displayed in the collection view cell

    cell?.aLabel.text = "Card:\(indexPath.row)"
    return cell!
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
   return folderCount!
}

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

now we are going the code the ViewController class now just past the below code

class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var cardCountArray:[Int] = []
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    cardCountArray = [5,15,6,12,7,10]
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
    return cardCountArray.count
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
   return  1
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell:CustomTableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL") as? CustomTableViewCell;
    if(cell == nil)
    {
        cell = CustomTableViewCell.CreateCustomCell()
    }
    cell?.folderCount = cardCountArray[indexPath.section]
    cell?.foldersCollectionView.reloadData()
    cell?.clipsToBounds = true
    return cell!;
}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
    return 100.0
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    var headerView:UIView = UIView(frame: CGRectMake(0, 0, tableView.bounds.size.width, 70.0))
    var labelTitle:UILabel = UILabel(frame: CGRectMake(0, 0, tableView.bounds.size.width, 35))
    var descriptionTitle:UILabel = UILabel(frame: CGRectMake(0, 20,tableView.bounds.size.width , 30))
    headerView.addSubview(labelTitle)
    headerView.addSubview(descriptionTitle)
    labelTitle.text = "TOTAL_CARDS in section:\(section)"
    descriptionTitle.text = "This CARD_SECTION contains \(cardCountArray[section]) CARDS"
    return headerView
}

 func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 50.0
  }
 }

result will be like below

if any thing missing please let me know

For your comment I have an array, for example, ["2C3C4C5C6C7C", "AD2D3D4D5D", "9H8H7H"]

for this u need to make below modification

//for first row u get like this
//the string for the row is 2C3C4C5C6C7C
//stringForCell = "2C3C4C5C6C7C"
//2C
//3C
//4C
//5C
//6C
//7C
//for other cells u can get like below
//the string for the row is AD2D3D4D5D
//stringForCell = "AD2D3D4D5D"
//AD
//2D
//3D
//4D
//5D
//the string for the row is 9H8H7H
//stringForCell = "9H8H7H"
//9H
//8H
//7H

//in controller controller class define array of string
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var cardCountArray:[Int] = []
var stringArray : [String] = []
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    stringArray = ["2C3C4C5C6C7C", "AD2D3D4D5D", "9H8H7H"] 
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
   // return cardCountArray.count
    return stringArray.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell:CustomTableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL") as? CustomTableViewCell;
    if(cell == nil)
    {
        cell = CustomTableViewCell.CreateCustomCell()
    }
    //cell?.folderCount = cardCountArray[indexPath.section]
    cell?.stringForCell = stringArray[indexPath.section];
    cell?.foldersCollectionView.reloadData()
    cell?.clipsToBounds = true
    return cell!;
}


//in custom tableview cell add a string variable
class CustomTableViewCell: UITableViewCell,UICollectionViewDataSource,UICollectionViewDelegate {

@IBOutlet weak var foldersCollectionView: UICollectionView!
var stringForCell:String = "" //add the string to hold the string

//rest of the code

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    var cell :CustomCollectionViewCell? = collectionView.dequeueReusableCellWithReuseIdentifier("FOLDER_CELL", forIndexPath: indexPath) as? CustomCollectionViewCell
    var str:NSString = stringForCell
    var length = str.length
    var totalLlength:Int =  length/2
    var indexStart   = indexPath.row * (2);
    var aRange = NSMakeRange(indexStart, 2)
    var cardString:NSString = str.substringWithRange(aRange)
    println(cardString)
    cell?.aLabel.text   = "Card: \(cardString)"
    return cell!
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

   println("the string for the row is \(stringForCell)")
    var str:NSString = stringForCell
    var length:Int = str.length
    return length / 2
   //return folderCount!
}

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

i written a detailed post about how to add collection view inside custom table view cell hear hope this gives more detailed explanation than this post.

这篇关于在UITableView原型中带有Images的UICollectionView单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆