我正在尝试使用UITableViewController创建表视图。
'cellForRowAtIndexPath'似乎没有正常工作 - 我已经从Parse预装了照片和评论并将它们放在一个数组中,并希望图片填满屏幕宽度,所以我正在做一些手册计算他们调整大小。
我正在做一些不寻常的事情让Table View看起来正确,但现在数据是重复的。
我知道这里有一些我没有得到的东西,但我不确定它是什么......也许我需要做一些别的事来绑定数据,或者用“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
}
}
答案 0 :(得分:2)
当您重新使用单元格时(这是一件好事!)每次调用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行之后,第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
时初始化您的单元格。
另外,我建议删除cellArray
而不存储对单元格的引用(出于与上面提到的相同的原因)。您可以缓存单元格高度,这应该没问题,因为它们与可重用单元格无关。你可以这样做:
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
。在这种情况下,在重新加载tableview之前,某些单元格的高度为0。请查看此帖子以获取更多信息:
Why does heightForRowAtIndexPath: come before cellForRowAtIndexPath:?