IOS 7 В режиме просмотра таблицы невозможно настроить настройку содержимого

Я переношу свой проект на iOS7. У меня возникла странная проблема, связанная с прозрачной навигационной панелью.

У меня есть контроллер представления и он имеет представление tableview как subview (позвольте ему назвать ControllerA). Я запускаю новый контроллер uinavigation с контроллером A и представляю его модально с помощью currentviewcontroller. Представленное представление таблицы контроллера просмотра блокируется навигационной панелью. Я установил автоматическиAdjustsScrollViewInsets на YES, но результат не изменился. Я знал, что могу установить edgeForExtendedLayout на UIRectEdgeNone, но это сделает навигационную панель более прозрачной.

Table view get blocked

После этого я попытался создать новый контроллер просмотра для тестирования. Он содержит почти те же элементы. Но результат сильно отличается. Содержимое таблицы не блокируется.

enter image description here

Заключение

  • Два контроллера просмотра автоматически присваивают параметрам YES:
  • Проект не использует раскадровку
  • Первый создается на Xcode 4.6, второй - на Xcode 5
  • Я сравнил два класса xib и code, не сильно отличающийся

Ответ 1

Я нашел ответ на форуме разработчиков Apple. Есть два разных случая.

Первый, добавленный контроллер просмотра - это UITableViewController. И проблема не должна появляться, так как Apple будет автоматически заполнять ее.

Второй, контроллер просмотра НЕ является UITableViewController. И в иерархии представлений он содержит UITableView. В этом случае, если UITableview (или ScrollView) является основным видом viewController или первым подзором основного вида, он будет работать. В противном случае диспетчер представлений не знает, какой вид прокрутки будет отложен, и это будет проблемой.

В моем случае контроллер просмотра является вторым. И есть представление фонового изображения в качестве первого подсмотра основного вида. Таким образом, он терпит неудачу.

Вот ссылка на форум разработчиков Apple (нужно получить доступ к учетной записи разработчика): https://devforums.apple.com/message/900138#900138

Ответ 2

Если вы хотите, чтобы представление перекрывало панель навигации, но также хотело, чтобы она располагалась так, чтобы верхняя часть содержимого scrollview располагалась под панелью навигации по умолчанию, вы можете добавить верхнюю вставку вручную, как только будет выведено представление. Это по существу то, что делает система макета вида, когда представление верхнего уровня представляет собой прокрутку.

-(void)viewDidLayoutSubviews {
    if ([self respondsToSelector:@selector(topLayoutGuide)]) {
        UIEdgeInsets currentInsets = self.scrollView.contentInset;
        self.scrollView.contentInset = (UIEdgeInsets){
            .top = self.topLayoutGuide.length,
            .bottom = currentInsets.bottom,
            .left = currentInsets.left,
            .right = currentInsets.right
        };
    }
}

Ответ 3

Основываясь на ответе Тони, я смог программно решить эту проблему, временно переведя табличное представление в обратную сторону, разрешив настройку, а затем отправьте фоновый вид назад. В моем случае нет никакого мерцания для этого подхода.

В контроллере просмотра:


- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    [self.view sendSubviewToBack:self.tableView];
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    [self.view sendSubviewToBack:self.backgroundView];
}

Очевидно, что если на self.view есть другие подзаголовки, вам может потребоваться также переопределить их.

Ответ 4

Вероятно, слишком много ответов на это уже было, но мне пришлось принять решение Кристофера и немного изменить его для поддержки изменения размера представления и разрешить изменение вставки содержимого в подклассе UIViewController.

@interface MyViewController ()

@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (assign, nonatomic) UIEdgeInsets scrollViewInitialContentInset;

@end


@implementation MyViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setScrollViewInitialContentInset:UIEdgeInsetsZero];
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    if (UIEdgeInsetsEqualToEdgeInsets([self scrollViewInitialContentInset], UIEdgeInsetsZero)) {
        [self setScrollViewInitialContentInset:[self.scrollView contentInset]];
    }
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    UIEdgeInsets scrollViewInset = [self scrollViewInitialContentInset];

    if (UIEdgeInsetsEqualToEdgeInsets(scrollViewInset, UIEdgeInsetsZero) {

        if ([self respondsToSelector:@selector(topLayoutGuide)]) {
            scrollViewInset.top = [self.topLayoutGuide length];
        }

        if ([self respondsToSelector:@selector(bottomLayoutGuide)]) {
            scrollViewInset.bottom = [self.bottomLayoutGuide length];
        }

        [self.scrollView setContentInset:scrollViewInset];
    }
}

@end

Чтобы объяснить точку:

Любой подкласс MyViewController теперь может изменять contentInset of scrollView в viewDidLoad, и он будет соблюдаться. Однако, если contentInset of scrollView UIEdgeInsetsZero: он будет расширен до topLayoutGuide и bottomLayoutGuide.

Ответ 5

@Решение Кристофера Пикслея в Swift 2:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let topInset = topLayoutGuide.length
    inTableView.contentInset.top = topInset
    inTableView.contentOffset.y = -topInset
    inTableView.scrollIndicatorInsets.top = topInset
}

Ответ 6

Да, немного раздражает.

У меня есть наконечник с одним представлением таблицы в основном представлении, не используя автозапуск. Существует панель, панель навигации и панель состояния, и приложение должно вернуться к 5.0. В конструкторе интерфейса, который аккуратно "видит его в iOS7 и iOS6.1", работает, показывая таблицы аккуратно подгоняемые (как только дельта iOS6/7 были установлены правильно).

Однако при работе на устройстве или симуляторе в верхней части таблицы наблюдался большой пробел, который был вызван вложением содержимого (которое в значительной степени соответствовало вертикальной дельтам iOS6/7), которое было установлено на ноль в СИБ.

Единственное решение, которое я получил, было в viewWillAppear для установки в [_tableView setContentInset: UIEdgeInsetsZero].

Еще один уродливый взлом с довольно наглядным результатом.....

Ответ 7

[self.navigationController setNavigationBarHidden:YES animated:YES]; 

в

- (void)viewDidLoad