使用UITableViewController cellForRowAtIndexPath获取重复的单元格
我正在尝试使用UITableViewController创build一个表视图。
'cellForRowAtIndexPath'似乎没有正确的工作 – 我已经预先加载的照片和评论从parsing,把他们在一个数组,并希望图片,填满屏幕宽度,所以我正在做一些手动计算resize。
我正在做一些不寻常的事情,让表视图看起来是正确的,但现在的数据是重复的。
我知道这里有些东西没有得到,但是我不确定它是什么…也许我需要做其他的事来绑定数据,或者用“prepareForReuse”方法做些什么?
我已经包含了UITableViewController子类和我写的UITableCell子类的代码。
import UIKit class YouTableViewCell: UITableViewCell { var recipeId:String = "" var recipeName:String = "" var imageHeight:CGFloat = 0 var labelHeight:CGFloat = 0 // DO I NEED THIS? override func prepareForReuse() { self.textLabel!.text = recipeId //Put your label name self.imageView!.image = nil } override func setSelected(selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } } class YouTableViewController: BaseTableViewController { // UITableViewController { var labelCreated = [Bool]() var imageCreated = [Bool]() var cellArray = [Int:YouTableViewCell]() override func viewDidLoad() { super.viewDidLoad() self.tableView.delegate = self self.tableView.dataSource = self self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer()) if !isYouDataLoaded { _ = DataController.getYouPageData() } // initialize height arrays for _ in 0..<youFeed.count { labelCreated.append(false) imageCreated.append(false) } // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem() self.navigationController?.setToolbarHidden(false, animated: false) } // ... skipping down override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // return feedArray.count return youFeed.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { print("cellForRowAtIndexPath : \(indexPath.row)") // Get reference to cell cellArray[indexPath.row] = (tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! YouTableViewCell) let thisCell:YouTableViewCell = cellArray[indexPath.row]! // TEMP -- Border thisCell.layer.borderWidth = 2.0 thisCell.layer.borderColor = UIColor.blackColor().CGColor let meal = youFeed[indexPath.row].recipe // If the image exists if let foodImage:UIImage = meal.imageView.image! as UIImage { var nameLabel:UILabel = UILabel() var fitImageView:UIImageView? if imageCreated[indexPath.row] == false { print("For IMAGE #\(indexPath.row)") fitImageView = LayoutHelper.fitImageInCell(foodImage, cell: thisCell, name: meal.recipeName) thisCell.contentView.addSubview(fitImageView!) thisCell.imageHeight = fitImageView!.frame.height fitImageView!.frame.origin.y = 0 print("img height : \(fitImageView!.image!.size.height)") imageCreated[indexPath.row] = true } if labelCreated[indexPath.row] == false { // Create Label var captionString = "" if let mealNameText:String = meal.recipeName as String { captionString += mealNameText } if let postText:String = meal.desc as String { captionString += "\n" + postText } else { print("Meal Desc is null") } if let numForks:Int = meal.forks as Int { captionString += "\n" + String(numForks) + " Forks" } if (fitImageView != nil) { nameLabel = LayoutHelper.fitLabelBelowImageView(captionString, imageView: fitImageView!, cell: thisCell, yOffset: 0) thisCell.addSubview(nameLabel) thisCell.labelHeight = nameLabel.frame.height } } } return thisCell } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let thisCell = cellArray[indexPath.row] var thisHt:CGFloat = 0 if thisCell != nil { thisHt = thisCell!.labelHeight + thisCell!.imageHeight } return thisHt } }
当你重新使用单元格时(这是一件好事!)每次调用cellForRowAtIndexPath
都必须重新初始化整个单元格。 这是因为当你打电话时有可能:
tableView.dequeueReusableCellWithIdentifier
它可能会返回已经初始化的单元格。 例如,假设屏幕上有4行可见:
Row 1 - Cell A [Image 1] Row 2 - Cell B [Image 2] Row 3 - Cell C [Image 3] Row 4 - Cell D [Image 4]
现在,让我们向下滚动,第1行不再在屏幕上,但第5行现在已经出现了。 第5行所接收的单元格可能与第1行中的单元格完全相同。因此,在调用tableView.dequeueReusableCellWithIdentifier
第5行后立即看起来如下所示:
Row 2 - Cell B [Image 2] Row 3 - Cell C [Image 3] Row 4 - Cell D [Image 4] Row 5 - Cell A [Image 1] <--
你需要更新单元格A指向图5.这可能在你的代码中正常工作,你会得到这个:
Row 2 - Cell B [Image 2] Row 3 - Cell C [Image 3] Row 4 - Cell D [Image 4] Row 5 - Cell A [Image 5] <--
现在,假设您向上滚动,第1行再次分配了单元格A:
Row 1 - Cell A [Image 5] <-- Row 2 - Cell B [Image 2] Row 3 - Cell C [Image 3] Row 4 - Cell D [Image 4]
由于您正在存储数组以跟踪哪些行已被初始化( imageCreated
, labelCreated
),单元格将不会更新为指向图像1:
// THIS WILL BE TRUE, SO IT WILL NOT EXECUTE if imageCreated[indexPath.row] == false
这意味着摆脱你的imageCreated
和labelCreated
数组,并执行代码,每次调用cellForRowAtIndexPath
初始化您的单元格。
此外,我会build议摆脱cellArray
和不存储引用单元格(出于同样的原因,我上面提到)。 你可以caching单元格的高度,这应该没问题,因为这些不是绑定到可重用的单元格。 你可以做这样的事情:
var cellHeightArray = [Int:CGFloat]()
由于您在cellForRowAtIndexPath
中进行计算,因此将底部的高度设置为:
cellHeightArray[indexPath.row] = thisCell!.labelHeight + thisCell!.imageHeight;
然后从heightForRowAtIndexPath
的数组中设置它:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let thisCellHeight = cellHeightArray[indexPath.row] var thisHt:CGFloat = 0 if thisCellHeight != nil { thisHt = thisCellHeight } return thisHt }
默认情况下,但我相信heightForRowAtIndexPath
之前调用cellForRowAtIndexPath
。 在这种情况下,你的一些单元格会有0的高度,直到你重新加载tableview。 看看这个post的更多信息:
为什么heightForRowAtIndexPath:在cellForRowAtIndexPath之前:?