HeathWang / HWPanModal

HWPanModal presents controller from bottom and drag to dismiss, high customize. iOS13 default modalPresentationStyle. 任意形式的底部弹框动画;头条、知乎、抖音弹出评论效果;地图浮层,iOS13 present默认模态效果。
MIT License
1.16k stars 197 forks source link

使用HWFullScreenNavController例子,如果子控制器是一个tableview,再次点击push新的子控制器之后,新子控制器的tableview不能滑动,pop上一个弹窗页面,也不能滑动 #145

Open hc2088 opened 9 months ago

hc2088 commented 9 months ago

参考demo写法在HWFullScreenNavController中编写:

- (UIScrollView *)panScrollable {
    __block UITableView *tableView;
    [[self.topViewController.view subviews] enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if([obj isKindOfClass:[UITableView class]]){
            tableView =obj;
        }
    }];
    return tableView;
}

使用HWFullScreenNavController例子,如果子控制器是一个tableview,再次点击push新的子控制器之后,tableview的滑动不生效 发现是scrollable.window这个为nil了导致

导致下面逻辑卡住不能滑动tableview

- (void)didPanOnScrollViewChanged:(NSDictionary<NSKeyValueChangeKey, id> *)change {

    UIScrollView *scrollView = [[self presentable] panScrollable];
    if (!scrollView) return;

    if ((![self isBeingDismissed] && ![self isBeingPresented]) ||
        ([self isBeingDismissed] && [self isPresentedViewControllerInteractive])) {

        if (![self isPresentedViewAnchored] && scrollView.contentOffset.y > 0) {
            [self haltScrolling:scrollView]; //isPresentedViewAnchored 为no 卡在这里 ,tableview不能滑动
        } else if ([scrollView isScrolling] || [self isPresentedViewAnimating]) {

            // While we're scrolling upwards on the scrollView, store the last content offset position
            if ([self isPresentedViewAnchored]) {
                [self trackScrolling:scrollView];
            } else {
                /**
                 * Keep scroll view in place while we're panning on main view
                 */
                [self haltScrolling:scrollView];
            }
        } else {
            [self trackScrolling:scrollView];
        }

    } else {
        /**
         * 当present Controller,而且动画没有结束的时候,用户可能会对scrollView设置contentOffset
         * 首次用户滑动scrollView时,会因为scrollViewYOffset = 0而出现错位
         */
         if ([self isBeingPresented]) {
             [self setScrollableContentOffset:scrollView.contentOffset animated:YES];
         }
    }
}

如上面, push子控制器后,tableview就不能再滑动了,现在的做法是

- (BOOL)allowsExtendedPanScrolling {
    if ([self panScrollable]) {
        UIScrollView *scrollable = [self panScrollable];

        /*
         [TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window.
         */
        //if (!scrollable.superview || !scrollable.window) return NO; // 这里去掉这个条件 !scrollable.window
        if (!scrollable.superview ) return NO;

        [scrollable layoutIfNeeded];
        return scrollable.contentSize.height > (scrollable.frame.size.height - self.bottomLayoutOffset);
    }

    return NO;
}

有什么更好的解决方法或者demo吗?

HeathWang commented 3 months ago

这里以前是解决警告问题加的,如果你这样运行没问题,这是最优解了