TableHeaderView поверх первой ячейки

Я пытаюсь создать табличный вид программно, у которого есть панель поиска в tableHeaderView. По какой-то причине строка поиска появляется поверх первой ячейки.

Я использую масонство для создания ограничений.

Может кто-то указать мне, что я делаю неправильно.

- (void)setupViews {

...
    self.tableView = [[UITableView alloc] initWithFrame:CGRectZero];
    [self.view addSubview:self.tableView];

    self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
    self.tableView.tableHeaderView = self.searchBar;
...
}

- (void)updateViewConstraints {

    [self.searchBar mas_updateConstraints:^(MASConstraintMaker *make) {
        make.width.equalTo(self.view);
        make.height.equalTo(@(44));
    }];

    [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.self.top.equalTo(self.view);
        make.self.bottom.equalTo(self.toolbar.mas_top);
        make.width.equalTo(self.view);
    }];
...
}

Problem

Здесь вы можете видеть, что заголовок находится на том же уровне, что и ячейки. View hierarchy

Ответ 1

Спасибо за вашу помощь, я нашел gist на GitHub, который говорил об изменении размера tableViewHeader с помощью AutoLayout:

https://gist.github.com/andreacremaschi/833829c80367d751cb83

- (void) sizeHeaderToFit {
    UIView *headerView = self.tableHeaderView;

    [headerView setNeedsLayout];
    [headerView layoutIfNeeded];
    CGFloat height = [headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    headerView.frame = ({
        CGRect headerFrame = headerView.frame;
        headerFrame.size.height = height;
        headerFrame;
    });

    self.tableHeaderView = headerView;
}

Если я вызову этот метод во время updateViewConstraints, он будет работать.

Однако я не совсем понимаю это.

Ответ 2

Использование расширения в Swift 3.0

extension UITableView {

    func setTableHeaderView(headerView: UIView?) {
        // set the headerView
        tableHeaderView = headerView

        // check if the passed view is nil
        guard let headerView = headerView else { return }

        // check if the tableHeaderView superview view is nil just to avoid
        // to use the force unwrapping later. In case it fail something really
        // wrong happened
        guard let tableHeaderViewSuperview = tableHeaderView?.superview else {
            assertionFailure("This should not be reached!")
            return
        }

        // force updated layout
        headerView.setNeedsLayout()
        headerView.layoutIfNeeded()

        // set tableHeaderView width
        tableHeaderViewSuperview.addConstraint(headerView.widthAnchor.constraint(equalTo: tableHeaderViewSuperview.widthAnchor, multiplier: 1.0))

        // set tableHeaderView height
        let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
        tableHeaderViewSuperview.addConstraint(headerView.heightAnchor.constraint(equalToConstant: height))
    }

    func setTableFooterView(footerView: UIView?) {
        // set the footerView
        tableFooterView = footerView

        // check if the passed view is nil
        guard let footerView = footerView else { return }

        // check if the tableFooterView superview view is nil just to avoid
        // to use the force unwrapping later. In case it fail something really
        // wrong happened
        guard let tableFooterViewSuperview = tableFooterView?.superview else {
            assertionFailure("This should not be reached!")
            return
        }

        // force updated layout
        footerView.setNeedsLayout()
        footerView.layoutIfNeeded()

        // set tableFooterView width
        tableFooterViewSuperview.addConstraint(footerView.widthAnchor.constraint(equalTo: tableFooterViewSuperview.widthAnchor, multiplier: 1.0))

        // set tableFooterView height
        let height = footerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
        tableFooterViewSuperview.addConstraint(footerView.heightAnchor.constraint(equalToConstant: height))
    }
}

Ответ 3

Здесь вопрос о пространстве между табличным представлением Заголовок и вид таблицы Cell. Вы можете обращаться с помощью Attribute Inspector. Пожалуйста, просмотрите это.   - выберите UITableView   - В разделе "Инспектор атрибутов" → "Размер прокрутки" → "Вставки содержимого", установите "Top = 44" (или в зависимости от вашей высоты навигационной панели).

Или вы можете обращаться с программным обеспечением.

  - (void)viewDidLoad {
       UIEdgeInsets inset = UIEdgeInsetsMake(20, 0, 0, 0);
       self.tableView.contentInset = inset;
   }

Ответ 4

Я думаю, проблема в том, что вы используете autolayout и устанавливаете кадры для просмотра вручную, замените этот код:

self.tableView = [[UITableView alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.tableView];

self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
self.tableView.tableHeaderView = self.searchBar;

с чем-то вроде этого:

self.tableView = [UITableView new];
self.tableView.translatesAutoresizingMasksIntoConstraints = NO;
[self.view addSubview:self.tableView];

self.searchBar = [UISearchBar new];
self.searchBar.translatesAutoresizingMasksIntoConstraints = NO;
self.tableView.tableHeaderView = self.searchBar;

Он может не работать, потому что, возможно, кадр searchBar's должен быть установлен вручную без ограничений.