Giter Site home page Giter Site logo

Comments (16)

smileyborg avatar smileyborg commented on May 23, 2024

You're likely running into the issue where the cell accessory view (disclosure indicator) is causing the cell's contentView to be smaller than the table view width, which breaks the height calculation. To fix this you'd need to set the cell size to the "correct" size (table view width minus width of accessory views and other things like a section index). Here is one of many posts about this issue: http://stackoverflow.com/questions/902096/uitableviewcells-contentviews-width-with-a-given-accessory-type There is no good way to do this that avoids hardcoding the values though.

The real solution is to use the self-sizing cell mechanism introduced in iOS 8. This of course is only available if your deployment target is 8.0 or higher. However, the self sizing cells will correctly take into account these cases.

Hope that helps.

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

So based on your answer and the link I changed

cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));

to

cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds) - 20, CGRectGetHeight(cell.bounds));

using the hardcoded value of 20.

The text is no longer truncated, but for some cells there is now a gap at the top of the body label.

So, did I make the width correction in the wrong place, or is something else going on as well?

I'm targeting iOS 7 and higher so unfortunately I cannot use the self-sizing cell mechanism introduced in iOS 8.

from tableviewcellwithautolayout.

smileyborg avatar smileyborg commented on May 23, 2024

That is the correct place/way to do it. You'll probably have to debug further, but it is possible that the disclosure indicator does not take up 20 pt (I'm not sure what the value is -- you can try setting a breakpoint at runtime and checking the frame of the contentView to see how much less than the table view's width it is).

If that's not the issue, it might have to do with your constraints. Hard to say for sure.

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

Thanks, I'll explore with other values. Just note, this is all in your sample code, so I'm assuming the constraints are ok :)

from tableviewcellwithautolayout.

smileyborg avatar smileyborg commented on May 23, 2024

Oh, if you haven't modified the sample code, then yes the constraints should be fine :) Please feel free to share your fork of the project on GitHub if you can't figure out what's going on.

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

Allright, I made a fork, and added some code adjustments to try to get the cell's dimensions to work. What I have currently is not yet working.

from tableviewcellwithautolayout.

smileyborg avatar smileyborg commented on May 23, 2024

OK I took at look at your fork. Definitely see the sizing issue.

I first ran the project on the iPhone 6 sim, and checked what the actual sizes of the table view cells and their content views were:

(lldb) po [self.tableView visibleCells][0]
<RJTableViewCell: 0x7ff228786ec0; baseClass = UITableViewCell; frame = (0 0; 375 393); autoresize = W; layer = <CALayer: 0x7ff228786ac0>>

(lldb) po [[self.tableView visibleCells][0] contentView]
<UITableViewCellContentView: 0x7ff228785b30; frame = (0 0; 341 392.5); gestureRecognizers = <NSArray: 0x7ff228787310>; layer = <CALayer: 0x7ff228786720>>

Note the width of the table view cell is the width of the screen (as expected): 375 pt. But the width of the contentView is 341 pt in this case (with the disclosure indicator).

So that means we want to factor in this 375 - 341 = 34 pt difference for the sizing operation.

Instead of setting the table view cell's bounds, I have found it more reliable to add a constraint to the contentView directly. (The reason setting the cell's bounds works in some cases is because the table view cell internally resizes and fixes the contentView to fit inside of it. I think Apple has changed the internal implementation between iOS 7 & 8 though.)

Anyways, here are both changes together:

CGFloat width = 0.0f;

if (cell.accessoryType == UITableViewCellAccessoryNone && cell.accessoryView == nil)
    width = CGRectGetWidth(tableView.bounds);
else
    width = CGRectGetWidth(tableView.bounds) - 34.0f;

//    cell.bounds = CGRectMake(0.0f, 0.0f, width, CGRectGetHeight(cell.bounds));

// Instead of setting the cell.bounds, add a constraint to the contentView directly that enforces the final width.
// Use a slightly less than Required priority to avoid any unintentional conflicts with the internal UITableViewCell constraints.
[UIView autoSetPriority:UILayoutPriorityRequired - 1 forConstraints:^{
    [cell.contentView autoSetDimension:ALDimensionWidth toSize:width];
}];

This seems to be working well for me on the iPhone 6 sim. Give it a try and let me know how that goes.

Note that you'll probably need to measure and hardcode the revised values for the accessory view width, for all the scenarios/devices as needed.

from tableviewcellwithautolayout.

smileyborg avatar smileyborg commented on May 23, 2024

One other note: that code above is incomplete, you'll want to make sure you store that constraint when you add it, so that you only add it once, and when the device rotates (or the table view otherwise changes width), you can simply update the constant of the constraint to the new width as needed.

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

Interestingly, on iOS 7 the difference is 33 pt. I have added that to my fork. Looks good now on both iOS versions, as well as on the iPhone 5(s) simulators.

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

I've noticed that adding

[UIView autoSetPriority:UILayoutPriorityRequired - 1 forConstraints:^{ [cell.contentView autoSetDimension:ALDimensionWidth toSize:width]; }];

decreases the performance of the table view, especially with long tables, scrolling becomes choppy. I have confirmed this with Instruments, there is at least a three-fold difference (in my app). My hunch is the slowdown is happening because this is called for every row and I am going to try to move this code to the updateConstraints method of the cell, so it will be called only once. I'll post back later with an update.

from tableviewcellwithautolayout.

smileyborg avatar smileyborg commented on May 23, 2024

That's interesting. You definitely don't want to duplicate that constraint more than once per cell, let me know how that goes. Can you also try testing the performance if you make the constraint Required priority (e.g. omit the autoSetPriority... call)? I know that optional constraints are more expensive to solve than Required ones, and theoretically it should work fine if the constraint is Required here.

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

Yeah, it's much faster if I comment out the autoSetPriority: call. Maybe it's an iOS7 vs iOS8 issue, still looking into that. If I understand correctly, I don't need heightForRowAtIndexPath: and estimatedHeightForRowAtIndexPath: in iOS8, but my app should work on iOS7 too so I need to keep it.

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

Allright, it's an iOS 7/8 issue.

If I run the code in iOS7 (simulator), there are no hiccups. If I run the code in iOS8 there are hiccups. But if I completely comment out heightForRowAtIndexPath: and estimatedHeightForRowAtIndexPath:, and set the values for the rowHeight and estimatedRowHeight in viewDidLoad, the hiccups in iOS8 are gone.

So I need to make my code work in both iOS7 and iOS8, and asked about that on SO: http://stackoverflow.com/questions/27944801/skip-ignore-method-in-ios/27945778

from tableviewcellwithautolayout.

smileyborg avatar smileyborg commented on May 23, 2024

Yeah, the iOS 8 self-sizing cells should be overall better than custom implementing that work yourself on iOS 7. So if possible you should use the self-sizing cell mechanism. This question asked the same question on SO already: http://stackoverflow.com/questions/26022113/how-to-only-override-a-method-depending-on-the-runtime-system-ios-version

I recommend using two different data source classes though, as opposed to conditionally making your view controller respond to that selector. But either should work.

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

Hope it's ok to ask this question here.

I've been trying to align the two UILabel views next to each other, and added that to my fork. What I see is:

  1. they are lined up correctly next to each other, so that part is working
  2. in iOS 7, I see all the text for the bodyLabel, but in some cases there is a lot of whitespace above and under it.
  3. in iOS 8, the text of the every bodyLabel is truncated.

Note, that I shortened the string length for the bodyLabel for clarity.

See my fork here https://github.com/koenvanderdrift/TableViewCellWithAutoLayout

Any suggestions how I can fix this?

from tableviewcellwithautolayout.

koenvanderdrift avatar koenvanderdrift commented on May 23, 2024

I solved the iOS 7 issue by adding:

    [UIView autoSetPriority:UILayoutPriorityFittingSizeLevel forConstraints:^{
        [self.bodyLabel autoSetContentHuggingPriorityForAxis: ALAxisHorizontal];
    }];

from tableviewcellwithautolayout.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.