3

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?

Community
  • 1
  • 1
spwoco
  • 83
  • 5
  • 1
    Is building the cell UI by code an option? I think it might really help you out in this case. – Marcos Griselli Aug 01 '15 at 13:11
  • @Plasher I don't see why not! Unfortunately I know very little about how that works; I've done a modest bit of programmatic layout building, but never with tableview cells. Would that indeed let me do what I need to do? – spwoco Aug 01 '15 at 13:22
  • Yes, I'm sure you'll be able to build something efficient and without having to create different cells for each case. Take a look at http://snapkit.io I've been using it for some time and makes things really easy. – Marcos Griselli Aug 01 '15 at 13:37
  • I have some spare time, I can help you out. Hop on https://chat.stackoverflow.com/rooms/84502/ios-swift-help – Marcos Griselli Aug 01 '15 at 13:38

1 Answers1

3

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.

enter image description here

While this one will not.

enter image description here

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.

Warren Burton
  • 17,451
  • 3
  • 53
  • 73
  • Wonderful. Thank you. But please help me understand something: How is this different than exactly what smileyborg says not to do in his answer to http://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights (under "2. Determine Unique Table View Cell Reuse Identifiers") Aren't I setting up cells with different constraints, and then adding them to the same reuse pool? Am I misunderstanding something? – spwoco Aug 01 '15 at 13:56
  • 1
    I didn't read that answer previously. Its the same thing as what I wrote here just more of it with extra background. No-one can tell you what your use cases are except you. Think of a cell as a white-board and when you dequeue you erase that white board and then put some new marks on it. Not all of your generic whiteboards are going to work for all cases, at which point you are going to make new types which you can switch in and out. The re-use process works because only visible cells (and a couple more) are in use at any one time. – Warren Burton Aug 01 '15 at 14:03
  • OK. Sorry, I'm not sure I phrased my question optimally but I think you've mostly answered anyway. Thanks. So to clarify, when smileyborg said "...The internal Auto Layout engine is not designed to handle large scale changes in constraints, and you will see massive performance issues" he's talking about much larger-scale constraint changes than what I'm (probably) trying to do, and therefore "performance issues" hopefully won't occur. Is this correct? So I should have general prototype cell that has most of what I need, and then modify it programmatically from there. Correct? – spwoco Aug 01 '15 at 14:21
  • Correct. Adding and removing constraints is heavy processing work for the engine so if you are doing that then yes you do need different types. but if it's just a few changes to a generic layout then you can probably stick with one. I highly recommend the 2 WWDC 2015 Autolayout sessions. They are a master class on this topic. – Warren Burton Aug 01 '15 at 16:40