UITableViewHeaderFooterView subclass with auto layout and section reloading won't work well together

后端 未结 11 1294
天涯浪人
天涯浪人 2020-12-30 23:04

I am trying to incorporate auto layout into my UITableViewHeaderFooterView subclass. The class is pretty basic, just two labels. This is the complete subclass:



        
相关标签:
11条回答
  • 2020-12-30 23:59

    I don't see where you call translatesAutoresizingMaskIntoConstraints = NO on the footer itself. Should you do this when you create it?

    - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier {
        self = [super initWithReuseIdentifier:reuseIdentifier];
        self.translatesAutoresizingMaskIntoConstraints = NO;
        MBTableDetailStyleFooterViewCommonSetup(self);
        return self;
    }
    
    0 讨论(0)
  • 2020-12-31 00:00

    Annoyingly, it looks like UITableViewHeaderFooterView doesn't like constant constraints e.g.

    |-10-[view]-10-|

    I guess because at creation the view has zero width and cannot satisfy the constraint, which would need at least a 20px width in this case.

    For me, the way around this was to change my constant constraints into something like

    |-(<=10)-[view]-(<=10)-|

    Which should satisfy a zero width content and should give the desired margin when resized.

    0 讨论(0)
  • 2020-12-31 00:03

    Working Solution as of iOS 9

    In your UITableViewHeaderFooterView subclass place the following code.

    - (void)setFrame:(CGRect)frame {
        if (frame.size.width == 0) {
            return;
        }
        
        [super setFrame:frame];
    }
    

    Explanation:

    The tableview handles the layout of the header views and it does so by manually manipulating the frames (yes even with autolayout turned on).

    If you inspect the width constraints that are on the header/footer views there are two, one contained on the superview (the table view) for the width, and one contained in the header/footer view itself for the width.

    The constraint contained on the super view is a NSAutoresizingMaskLayoutConstraint which is the giveaway that the tableview depends on frames to manipulate the headers. Switching the translatesAutoresizingMaskIntoConstraints to NO on the header view affectively breaks its appearance which is another give away.

    It appears that under some circumstances these header/footer views will have their frames change to a width of zero, for me it was when rows were inserted and the header views were reused. My guess is that somewhere in the UITableView code a preparation for an animation is made by starting the frame at zero width, even if you are not using an animation.

    This solution should work well and should not impact scroll performance.

    0 讨论(0)
  • 2020-12-31 00:04

    I had a similar problem with just one extra label in the contentView. Try to insert

    static void MBTableDetailStyleFooterViewCommonSetup(MBTableDetailStyleFooterView *_self) {
        _self.contentView.translatesAutoresizingMaskIntoConstraints = NO
        [...]
    }
    

    at first line in your MBTableDetailStyleFooterViewCommonSetup function. For me, this works in conjunction with reloadSections:withRowAnimations:.

    Update:

    I also added a new constraint for the contentView to use all width:

    NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|"
                                                                              options:0
                                                                              metrics:nil
                                                                                views:@{@"contentView" : _self.contentView}];
    [_self.contentView.superview addConstraints:horizontalConstraints];
    
    0 讨论(0)
  • 2020-12-31 00:05

    I ran in to this last week.

    The way that I've eliminated the warnings is to change my required constraints to have a priority of 999. This is a work around rather than a fix, but it does get around exceptions being thrown, caught and logged during layout.

    Things that didn't work for me.

    A suggestion is to set estimatedRowHeight . I tried to set the estimatedSectionHeaderHeight, but this didn't help. Setting an estimatedSectionFooterHeight created empty footers where I didn't want them, which was a bit odd.

    I also tried setting translatesAutoresizingMaskIntoConstraints = NO; on the header footer view, and on its content view. Neither got rid of the warning and one lead to the layout breaking completely.

    0 讨论(0)
提交回复
热议问题