Reputation: 83
Apologies in advance if this has been answered somewhere. I've looked everywhere and I'm still unsure what to do. (And answers that use Objective C are almost completely worthless to me.) I'm somewhat new to iOS.
I have a UITableView which serves as a newsfeed of sorts, displaying a series of posts. (a la a twitter newsfeed, for instance.) The cells in this table view are (currently) derived from a single cell prototype, created in xcode's interface builder. Each cell contains subviews to display things like username, profile image thumbnail, title, message, date, location, another image, etc.
The problem is, depending on what data a particular post contains, many of these subviews either should or should not be shown -- if a post doesn't contain an image, then that cell's image view should not be shown; if a post doesn't have a date and/or location, one or both of these views should not be shown. Not only should the unused fields be empty, but they shouldn't take up any space in the cell.
I read in Using Auto Layout in UITableView for dynamic cell layouts & variable row heights (under "2. Determine Unique Table View Cell Reuse Identifiers". Wonderful answer by @smileyborg, btw.) that for each different layout of subviews that could be in a cell, a different prototype cell and reuse identifier should be used. But this would require me to have a cell prototype for every single possible combination of data items in a post, even if the difference is single label! Surely there must be a better way.
What is the safe and correct way to do what I need to do? Is there perhaps a way to remove subviews from cells at runtime (and have the layout adjust its spacing accordingly) without completely screwing up cell recycling?
Upvotes: 3
Views: 933
Reputation: 17372
Ill assume you know everything you want to know about your layout when you see the cell.
So its basic tableview cell layout. Dequeue and decorate.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(MyIdentifier, forIndexPath: indexPath) as! MyCustomCellClass
let data:MyDataClass = myDataAtIndexPath(indexPath)
decorateCell(cell,data:data)
return cell
}
func decorateCell(cell:MyCustomCellClass,data:MyDataClass) {
//here is where you arrange/change your constraints and hide/reveal views
//depending on the data
}
but also what you need is to allow the cell to set its height properly
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return someEstimatedNumberWhichIsClose;
}
but most crucially in your XIB, the cell MUST have a continuous line of constraints from top to bottom which describe the height.
So this cell will auto-set its height correctly.
While this one will not.
NB - in the upper example , if you leave the height constraint off the text-field and make it infinite line count the cell will grow/shrink appropriately.
So to summarise you can use one multipurpose cell as long as you keep your height constraints coherent.
As a general rule - Swiss Army Cells® which do lots of things may get a bit unwieldy so you do need think about how many use cases you wish to support with one cell and then maybe start creating multiple types/identifiers.
Upvotes: 3