Autolayout + UITableView generates phantom section headers on iOS 6

So, I inherited a project with some code in it, a type of behavior like iMessage.

enter image description here

There are two types: the top, which goes from the navigation bar, to the composed message, one and the bottom, which is the message below.

It is assumed that the composite message should grow in height whenever the entered text spans more than one line, therefore, when the keyboard is displayed in the container view, the following auto-detection rules are set:

 NSDictionary *viewsToConstrain = NSDictionaryOfVariableBindings(bottomView, topView);
    _vConstraints = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|[topView]-(0)-[bottomView]-(==%.1f)-|", keyboardHeight]
                                                            options:NSLayoutFormatAlignAllCenterX
                                                            metrics:nil
                                                              views:viewsToConstrain];

Thus, when you enter text as a text view, the layout block becomes larger and the tableView with messages becomes smaller:

enter image description here

Whenever you press the submit button, a Message object is created and stored in CoreData. The view controller, which hosts the table view and the message view for composing the message, has a selected result controller that adds the newly created message to the table view using some standard UITableView animation:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
        [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{

        switch (type)
        {
            case NSFetchedResultsChangeInsert:

                    [self.tableView insertRowsAtIndexPaths:@[newIndexPath]
                                          withRowAnimation:UITableViewRowAnimationTop];

                break;

                ...
                // Handle all the other cases
        }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];
}

And everything is working fine. Now that the message is long enough, the layout view becomes so high that the height of the table view becomes 0.

enter image description here

When you click Submit in this state

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

the method in the table view is called and a new header is added, even if

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
Method

returns the correct number of headers (in this case 1), and a second header is added, although it should not have been.

enter image description here

, .

, , :

enter image description here

, , 0, iOS 7.

, beginUpdates endUpdates insertRowsAtIndexPaths:withRowAnimation: reloadData - iOS 6.

, : , tableView , - , , , phantom, , .

iOS6, iOS 7 , , .

?

Edit:

viewForHeaderInSection

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UITableViewHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kSectionHeaderXibIdentifier];
    UILabel *textLabel = (UILabel *)[view viewWithTag:kSectionHeaderTextTag];
    if (!textLabel)
    {
        // we have no subviews yet, so create them

        view.contentView.backgroundColor = [UIColor whiteColor];

        textLabel = [UILabel autoLayoutView];
        textLabel.tag = kSectionHeaderTextTag;
        textLabel.backgroundColor = [UIColor clearColor];
        [view.contentView addSubview:textLabel];

        UIView *leftArt = [UIView autoLayoutView];
        leftArt.backgroundColor = kSectionOrnamentColor;
        [view.contentView addSubview:leftArt];

        UIView *rightArt = [UIView autoLayoutView];
        rightArt.backgroundColor = kSectionOrnamentColor;
        [view.contentView addSubview:rightArt];

        NSDictionary *bindingViews = NSDictionaryOfVariableBindings(textLabel, leftArt, rightArt);

        NSString *horzFormat = @"H:|-(12)-[leftArt(>=0)]-(8)-[textLabel]-(8)-[rightArt(leftArt)]-(12)-|";
        [view.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:horzFormat
                                                                                options:0
                                                                                metrics:nil
                                                                                  views:bindingViews]];

        [view.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(28.)-[leftArt(1)]-(>=0)-|"
                                                                                 options:0 metrics:nil views:bindingViews]];

        [textLabel pinToSuperviewEdges:JRTViewPinTopEdge inset:14.];
        [rightArt pinAttribute:NSLayoutAttributeTop toSameAttributeOfView:leftArt];
        [rightArt pinAttribute:NSLayoutAttributeHeight toSameAttributeOfView:leftArt];
    }

    textLabel.attributedText = [self titleForHeaderInSection:section];

    [textLabel invalidateIntrinsicContentSize];
    [view.contentView needsUpdateConstraints];

    return view;
}

.

+3

All Articles