I'm getting pretty sick of Auto Layout with UITableView
now…
Apple's docs and code demos all seem to work for them, but when I try it I get no luck. I've even deleted and rebuilt nibs from scratch just to see if I've set properties inadvertently… Twice.
Trouble is, this time round I've got Auto Layout cells working, woo? No. They only resize when scrolled out of the viewport and back in. (I'm guessing by a reload of some kind).
Has anyone come across this issue? There's a few questions similar to it on SO but no fixes, just discussions of how it must be a bug.
Here is my code:
Called on the UITableView
's IBOutlet
didSet
method:
private func loadHeadlinesTableView()
{
headlinesTableView.delegate = self
headlinesTableView.dataSource = self
// Register classes/nibs
headlinesTableView.registerClass(HeadlineHeroTableViewCell.self, forCellReuseIdentifier: CellIdentifiers.HeroHeadline)
headlinesTableView.registerNib(UINib(nibName: "HeadlineHeroTableViewCell", bundle: nil), forCellReuseIdentifier: CellIdentifiers.HeroHeadline)
headlinesTableView.registerClass(HeadlineBigTableViewCell.self, forCellReuseIdentifier: CellIdentifiers.BigHeadline)
headlinesTableView.registerNib(UINib(nibName: "HeadlineBigTableViewCell", bundle: nil), forCellReuseIdentifier: CellIdentifiers.BigHeadline)
headlinesTableView.registerClass(HeadlineMediumTableViewCell.self, forCellReuseIdentifier: CellIdentifiers.MediumHeadline)
headlinesTableView.registerNib(UINib(nibName: "HeadlineMediumTableViewCell", bundle: nil), forCellReuseIdentifier: CellIdentifiers.MediumHeadline)
headlinesTableView.registerClass(HeadlineSmallTableViewCell.self, forCellReuseIdentifier: CellIdentifiers.SmallHeadline)
headlinesTableView.registerNib(UINib(nibName: "HeadlineSmallTableViewCell", bundle: nil), forCellReuseIdentifier: CellIdentifiers.SmallHeadline)
// Automatic cell height
headlinesTableView.rowHeight = UITableViewAutomaticDimension
headlinesTableView.estimatedRowHeight = 128
headlinesTableView.backgroundView = nil
headlinesTableView.backgroundColor = UIColor.clearColor()
}
cellForRowAtIndexPath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
if tableView.isEqual(headlinesTableView)
{
// Headlines
var cell: HeadlineTableViewCell!
switch indexPath.section
{
case HeadlineSections.Index.HeroHeadlines:
// Hero
cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifiers.HeroHeadline, forIndexPath: indexPath) as? HeadlineHeroTableViewCell
case HeadlineSections.Index.BigHeadlines:
// Big
cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifiers.BigHeadline, forIndexPath: indexPath) as? HeadlineBigTableViewCell
case HeadlineSections.Index.MediumHeadlines:
// Medium
cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifiers.MediumHeadline, forIndexPath: indexPath) as? HeadlineMediumTableViewCell
case HeadlineSections.Index.SmallHeadlines:
// Small
cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifiers.SmallHeadline, forIndexPath: indexPath) as? HeadlineSmallTableViewCell
default:
break
}
// Return cell
return cell
}
return UITableViewCell()
}
willDisplayCell:
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
{
if tableView.isEqual(headlinesTableView)
{
// Headlines
let headlineCell = cell as! HeadlineTableViewCell
let headline = headlineForIndexPath(indexPath)
headlineCell.configureWithHeadline(headline)
if let thumbnailURL = headline.thumbnailURL
{
headlineImageForURL(thumbnailURL, completionHandler: { (thumbnail) -> () in
headlineCell.configureWithThumbnail(thumbnail)
})
}
}
}
didEndDisplayingCell:
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
{
if tableView.isEqual(headlinesTableView)
{
// Headlines
let headline = headlineForIndexPath(indexPath)
if let cacheKey = headline.thumbnailURL?.absoluteString, let downloader = headlineImagesDownloading[cacheKey]
{
downloader.cancelRetreivingThumbnailImage()
headlineImagesDownloading.removeValueForKey(cacheKey)
}
}
}
Custom cell class:
class HeadlineTableViewCell: UITableViewCell
{
// MARK: - Properties
// MARK: Outlets
@IBOutlet private weak var headlineImageView: UIImageView!
@IBOutlet private weak var headlineTitleLabel: UILabel!
@IBOutlet private weak var headlineDescriptionLabel: UILabel!
// MARK: - View Lifecycle
override func awakeFromNib()
{
super.awakeFromNib()
// Initialization code
}
// MARK: - Methods
func configureWithHeadline(headline: Headline?)
{
headlineTitleLabel?.text = headline?.title
headlineDescriptionLabel?.text = headline?.paragraph
}
func configureWithThumbnail(thumbnail: UIImage?)
{
headlineImageView?.image = thumbnail
}
}
Here's some screenshots of my custom cell nib. It was more advanced but now I'm struggling with just a label…
I know it's a lot but I really have no idea where I could be going wrong here… Thanks
Okay, so after a ton of work and nearly having to buy AppleCare before “accidentally” dropping my Mac against a wall, it seems any calls to tableView(_:willDisplayCell:forRowAtIndexPath:)
whereby you might affect the contents of a cell, ie like my cell configuration methods, disrupts Auto Layout.
I'm sure I read somewhere that tableView(_:willDisplayCell:forRowAtIndexPath:)
is supposed to be used for cell configuration but a closer look at Apple Docs says:
A table view sends this message to its delegate just before it uses cell to draw a row, thereby permitting the delegate to customize the cell object before it is displayed. This method gives the delegate a chance to override state-based properties set earlier by the table view, such as selection and background color. After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.
“Customise the cell object before it is displayed”, not its contents.
Annoyingly there's a little confusion as tableView(_:cellForRowAtIndexPath:)
doesn't say you should customise the contents in that method:
The returned UITableViewCell object is frequently one that the application reuses for performance reasons. You should fetch a previously created cell object that is marked for reuse by sending a dequeueReusableCellWithIdentifier: message to tableView. Various attributes of a table cell are set automatically based on whether the cell is a separator and on information the data source provides, such as for accessory views and editing controls.
In the words of Dumbledore, "well that was fun."
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.