Why does my UITableView's formatting go completely awry when I return from a view controller I segued to?

时光总嘲笑我的痴心妄想 提交于 2020-01-02 08:13:08

问题


I have a UITableView with a custom cell, which has a few labels in it that dynamically decide the height of the cell. When I tap on one cell and segue to a new view controller, upon returning all the formatting for the cells is completely messed up, and I can't figure out what is causing it.

Here is what the cells normally look like:

And I have some pretty basic constraints set on them. The top label is pinned to the top and left margins, and must always be >= 20 from the right. The other labels are aligned to the left of this first label, with vertical spacing set between all of them. The middle label has a right spacing constraint to the margin, and the bottom labels are aligned to the baseline of the first and have horizontal spacing between all of them.

When I segue back to this table view it looks like this however:

I can't figure out what is causing it to layout differently than when I left. If I scroll around it seems to "reset" them back to what they should be, but on initial load they're really messed up. I can attach the project if desired, but there's really not much outside of the Storyboard.

cellForRowAtIndexPath:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as CustomTableViewCell

    let object = objects[indexPath.row]

    cell.title1.text = object.name
    cell.title2.text = object.color
    cell.title3.text = object.roar

    return cell
}

Sample project: http://cl.ly/040L2z0q0V2d


回答1:


It appears that the table view cells aren't resizing based on the contents when returning from the segue. Using the sample project, I threw a reload data in the viewWillAppear and that seemed to fix the issue.

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.tableView.reloadData()
}



回答2:


There are actually couple of issues with your project.

Data Loading and AutoLayout.

The first one is causing a strange behavior at the time of drawing the cells with data. When unwinding from the segue you'll see those additional cells on top of your table caused by ambiguous layout calculation.

Solution: Move the data into override func viewWillAppear(animated: Bool) { and perform a tableView.reloadData() (as correctly suggested by @rFessler).

On the other hand, Autolayout is a kind of fiery beast. Tamable. It's worth investigating the topic further. I wasn't able to make your layout work with autosizing cell height but I'll leave few references and the project for you.


References:

http://www.appcoda.com/self-sizing-cells/

http://captechconsulting.com/blog/tyler-tillage/ios-8-tutorial-series-auto-sizing-table-cells


Project: http://cl.ly/3z3a2Z3a3U2K




回答3:


I've had a similar problem myself. I downloaded your project and it seems I've solved it by removing and tweaking some constraints. This is how my constraints look now:

Also I've added this to viewDidLoad:

self.tableView.estimatedRowHeight = 120
self.tableView.rowHeight = UITableViewAutomaticDimension

I also added this to test delete:

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete
    {
        self.objects.removeAtIndex(indexPath.row)

        self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    }
}

Now you can even rotate the device and remove rows and it's all working splendid!


However, there's still problem if you push this view on a Navigation Controller (Which is what my problem was about in the beginning). See my storyboard below to get some funky labels:

To solve this, it seems we actually have to do a hack! (Damn you apple, what is going on with this?!)

var firstAppearance=true
override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    if firstAppearance
    {
        if let indexPaths = self.tableView.indexPathsForVisibleRows()
        {
            self.tableView.reloadRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.None)
            self.firstAppearance = false
        }
    }
}

At the moment, I think this is as good as it gets.




回答4:


I played with this and find a simple solution, add this seems to fix the problem.

override func viewWillDisappear(animated:Bool) {
    super.viewWillDisappear(animated)
    self.tableView.estimatedRowHeight = 166.0
}



回答5:


Since the the method tableView:estimatedHeightForRowAtIndexPath will be called every time you segue to a new MVC, and change the autolayout, you can just do

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

to reuse the autolayout



来源:https://stackoverflow.com/questions/26610403/why-does-my-uitableviews-formatting-go-completely-awry-when-i-return-from-a-vie

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!