UIPageViewController предотвращает прокрутку моего табличного представления вверх при нажатии на строку состояния

StackOverflow https://stackoverflow.com//questions/21033238

Вопрос

Я поискал, прежде чем опубликовать этот вопрос, но ничего не смог найти.

У меня огромная проблема.У меня есть UIPageViewController типа прокрутки в качестве основы моего приложения с 3 контроллерами просмотра.

Один из контроллеров представления (listTableView) имеет табличное представление и контроллер отображения поиска.

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

Я ценю любую предложенную помощь.

Я знаю, что кто-то запросит код, даже если в данном случае он не имеет значения, но здесь он предназначен для создания UIPageViewController:

#import "MainViewController.h"

@interface MainViewController ()

@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSArray *contentViewControllers;

@end

@implementation MainViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageView"];
    self.pageViewController.dataSource = self;

    UIViewController *settings = [self.storyboard instantiateViewControllerWithIdentifier:@"Settings"];

    UIViewController *listTableView = [self.storyboard instantiateViewControllerWithIdentifier:@"List"];

    UIViewController *first = [self.storyboard instantiateViewControllerWithIdentifier:@"First"];

    self.contentViewControllers = [NSArray arrayWithObjects:settings,listTableView,first,nil];

    [self.pageViewController setViewControllers:@[first] direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];

    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];
    [self.pageViewController didMoveToParentViewController:self];

    self.view.backgroundColor = [UIColor colorWithRed:(248.0/255.0) green:(248.0/255.0) blue:(248.0/255.0) alpha:1.0];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
  viewControllerBeforeViewController:(UIViewController *)viewController {

    NSUInteger index = [self.contentViewControllers indexOfObject:viewController];

    if (index == 0) {
        return nil;
    }

    return self.contentViewControllers[index - 1];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
   viewControllerAfterViewController:(UIViewController *)viewController {

    NSUInteger index = [self.contentViewControllers indexOfObject:viewController];

    if (index >= self.contentViewControllers.count - 1) {
        return nil;
    }

    return self.contentViewControllers[index + 1];
}
Это было полезно?

Решение

Решение

После общения мы обнаружили кое-что интересное.Контроллер просмотра страницы сохраняет представления других контроллеров просмотра внутри иерархии представлений, поэтому они также фиксируют scrollsToTop поведение и вмешательство.Это означает, что вам нужно отключить scrollsToTop для каждого прокручиваемого вида внутри viewWillDisappear: из исчезающих контроллеров просмотра (и снова включите на viewWillAppear:).


Первоначальное расследование

Быстрый и простой способ:Scrollview является единственным вложенным представлением UIPageViewControllerвид со стороны:

self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];

Проверка в отладчике:

(lldb) po [self.pageViewController.view recursiveDescription]
<_UIPageViewControllerContentView: 0x8d7c390; frame = (0 0; 320 480); clipsToBounds = YES; opaque = NO; autoresize = W+H; layer = <CALayer: 0x8d7c4a0>>
   | <_UIQueuingScrollView: 0xa912800; frame = (0 0; 320 480); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x8d7cc90>; layer = <CALayer: 0x8d7c7e0>; contentOffset: {320, 0}>
   |    | <UIView: 0x8d7da00; frame = (0 0; 320 480); layer = <CALayer: 0x8d7da60>>
   |    | <UIView: 0x8d7dab0; frame = (320 0; 320 480); layer = <CALayer: 0x8d7db10>>
   |    | <UIView: 0x8d7db40; frame = (640 0; 320 480); layer = <CALayer: 0x8d7dba0>>

Вы могли бы использовать несколько методов для доступа к этому scrollview.Проще всего повторить self.pageViewController.view.subviews и найдите тот, который является подклассом UIScrollView.Поскольку это единственное вложенное представление, ваш цикл завершится после одной итерации.

Является ли это решение оптимальным?Нет.Подвержен ли он ошибкам?Теоретически, конечно.Есть ли вероятность, что это изменится?Маловероятно, поскольку иерархия представлений довольно логична.Это, по крайней мере, дает вам быстрое решение, вместо того чтобы иметь дело с изменением всей структуры приложения из-за небольшой оплошности Apple (предоставление пользователю доступа к scrollview).

Вы должны открыть запрос функции в Apple по адресу https://bugreport.apple.com.

Другие советы

Документы по iOS 7 на -scrollToTop сказать

На iPhone жест прокрутки вверх не имеет эффекта, если на экране есть более одного вида прокрутки, для которого scrollsToTop установлено значение YES.

Я использую UIPageViewController таким же образом, как и вы;одним из моих контроллеров страниц является UITableViewController.Так что я прихожу в замешательство от two-scrollviews-onscreen-no-scrolltotop политика.

Идея Кайла реализовать ваше собственное поведение scrollToTop с помощью невидимой кнопки, вероятно, является вашей самой надежной ставкой в этой ситуации.

В моем случае у меня был UITableView в UIPageViewControllerдочерние элементы просматривают контроллеры.Основываясь на предложениях Лео Натана, добавление этого в мой дочерний контроллер просмотра выполнило свою работу:

- (void)viewWillAppear:(BOOL)animated 
{
    [super viewWillAppear:animated];
    self.tableView.scrollsToTop = YES; 
}

- (void)viewWillDisappear:(BOOL)animated 
{
    [super viewWillDisappear:animated];
    self.tableView.scrollsToTop = NO; 
}

Как уже упоминалось, конкурирующие UIScrollView's в дочерних контроллерах представления будут мешать методу делегирования scrollsToTop друг друга.Этот код гарантирует, что только у одного из них одновременно включена функция scrollsToTop.

Я использовал это:

for v in view.subviews {
    if v.isKindOfClass(UIScrollView) {
        (v as! UIScrollView).scrollsToTop = false
    }
}
.

Но если есть еще другие ScrollViews, которые могут прокрутить наверх, ваш не будет работать.Используйте этот скрипт, чтобы узнать другие прокрутки ScrollsViews: https://stackoverflow.com/a/334437577/2589276 , затем отключите их прокрутки вверху.

Тогда в ViewController, где вы хотите прокрутить наверх, добавьте их:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    tableView.scrollsToTop = true
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    tableView.scrollsToTop = false
}
.

Я думаю, что лучшее решение будет использовать следующие два метода протокола UipageViewControllerDelegate (быстрая и грязная версия, учитывая, что есть только один контроллер просмотра на экране):

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers
{
    ((UITableViewController *)pendingViewControllers[0].tableView).scrollsToTop = YES;
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    ((UITableViewController *)previousViewControllers[0].tableView).scrollsToTop = NO;
}
.

Редактировать: Лучше Используйте Подход, изложенный в последнем абзаце принятого ответа

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top