一尘不染

iOS App在PushViewController上冻结

swift

我的导航控制器会间歇性地在推送时冻结。似乎将新的视图控制器添加到堆栈中,但是动画从未发生。我还有另外两个在屏幕上保存视图控制器的容器,在导航控制器冻结后,我可以与它们进行交互。真正有趣的是,如果我尝试将另一个视图控制器推送到导航控制器的堆栈上,我会注意到堆栈顶部还有一个额外的视图控制器(我最初推送的视图控制器冻结了导航控制器)。因此,如果我在主屏幕上(我们将其称为VC-
Home),并且尝试推送新视图(VC-1)并冻结,则尝试推送新视图(VC-2),这是我在推送之前在当前堆栈中看到的内容:

{ [VC-Home, VC-1] }

在调用pushViewController之后,它保持不变;VC-2未添加到堆栈中。

据我所知,导航控制器通过在动画开始之前使先前的视图控制器处于非活动状态来启动动画,但是随后动画从未发生,从而使导航控制器处于冻结状态。

我正在通过调用情节提要创建新的视图控制器, UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController")因此我认为那里没有任何问题。我也没有在导航栏上覆盖pushViewController。我的应用程序的一些独特之处在于,它的图像非常高分辨率(使用SDWebImage进行管理),并且我总是同时在屏幕上拥有三个容器(一个导航控制器,一个用于搜索的视图控制器以及一个交互式装订线/侧面/滑出菜单)。

CPU使用率低,内存使用率正常(发生冻结时,设备上稳定在60-70MB左右)。

是否有任何可能导致此问题的想法或任何调试技巧可以帮助我发现真正的问题?

更新资料

UINavigationController没有唯一的代码,因为我只是使用pushViewController()进行推送。这是调用它的代码:

func didSelectItem(profile: SimpleProfile) {
     let vc = UIStoryboard.profileViewController()
     vc.profile = profile
     navigationController?.pushViewController(vc, animated: true)
}

我推送的ViewController在viewDidLoad中具有以下代码:

override func viewDidLoad() {
    super.viewDidLoad()
    button.roundView()

    if let type = profile?.profileType {
        //load multiple view controllers into a view pager based on type 
        let viewControllers = ProfileTypeTabAdapter.produceViewControllersBasedOnType(type)
        loadViewPagerViews(viewControllers)

        let topInset = headerView.bounds.height + tabScrollView.contentSize.height
        if let viewPager = viewPager {
            for view in viewPager.views {
                if let tempView = view as? PagingChildViewController {
                    tempView.profile = fullProfile
                    tempView.parentVCDelegate = self
                    tempView.topInset = topInset
                }
            }
        }
    }
}

func loadViewPagerViews(viewControllers: [UIViewController]) {
    viewPager?.views = viewControllers
    viewPager?.delegate = self

    //loading views into paging scroll view (using PureLayout to create constraints)
    let _ = subviews.map { $0.removeFromSuperview() }
    var i = 0
    for item in views {
        addSubview(item.view)
        item.view.autoSetDimensionsToSize(CGSize(width: tabWidth, height: tabHeight))
        if i == 0 {
            item.view.autoPinEdgeToSuperviewEdge(.Leading)
        } else if let previousView = views[i-1].view {
            item.view.autoPinEdge(.Leading, toEdge: .Trailing, ofView: previousView)
        }
        if i == views.count {
            item.view.autoPinEdgeToSuperviewEdge(.Trailing)
        }
        i += 1
    }

    contentSize = CGSize(width: Double(i)*Double(tabWidth), height: Double(tabHeight))
}

更新2

我终于再次冻结了它。该应用程序在后台运行,我将其重新带回并尝试在冻结时将视图控制器推入堆栈。我注意到正在播放动画。我在页面顶部有一个滚动视图,它每10秒翻阅一次其内容(该应用程序会存储顶部横幅)。在冻结时,我注意到横幅是动画的中期。

这是我的UIScrollView中的滚动功能,每10秒调用一次:

func moveToNextItem() {
    let pageWidth: CGFloat = CGRectGetWidth(frame)
    let maxWidth: CGFloat = pageWidth * CGFloat(max(images.count, profileImages.count))
    let contentOffset: CGFloat = self.contentOffset.x
    let slideToX = contentOffset + pageWidth

    //if this is the end of the line, stop the timer
    if contentOffset + pageWidth == maxWidth {
        timer?.invalidate()
        timer = nil
        return
    }

    scrollRectToVisible(CGRectMake(slideToX, 0, pageWidth, CGRectGetHeight(frame)), animated: true)
}

我不记得有发生过动​​画/滚动的情况,因此没有按下过按钮,但是我可能是错的。

我还重新检查了堆栈,并且与上述相同的情况仍然存在,其中[VC-
Home,VC-1]是堆栈,而VC-2没有被推入。我还检查了VC-1的变量,并且一切都已加载(数据调用和图像加载)。

更新3

到第二点,这变得越来越陌生。我已经覆盖了pushViewController,所以可以在其中放置一个断点,并根据Alessandro
Ornano的响应进行一些调试。如果我未成功推送视图控制器,则将我的应用程序发送到后台,在pushViewController调用中放置一个断点,然后再返回该应用程序,该断点将立即被击中多次。如果然后我继续经过所有命中,则下一个视图控制器突然变为可见,并且我尝试推送的最后一个视图控制器现在作为最后一个视图控制器进入堆栈。这意味着我看到的那个人仍然被禁用,这实际上使我处于与以前相同的位置。


阅读 379

收藏
2020-07-07

共1个答案

一尘不染

几周前,我们遇到了同样的问题。对于我们的问题,我们将其范围缩小到left-edge pop gesture recogniser。您可以尝试使用以下步骤检查是否可以重现此问题

  • 当没有下方的视图控制器时(例如,在根视图控制器上,请尝试使用左边缘弹出手势VC-Home
  • 此后,尝试单击任何UI元素。

如果能够重现冻结,请interactivePopGestureRecognizer在视图控制器堆栈只有一个视图控制器时尝试禁用。

- (void)navigationController:(UINavigationController *)navigationController
   didShowViewController:(UIViewController *)viewController
                animated:(BOOL)animate
{
    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
{
        if (self.viewControllers.count > 1)
        {
            self.interactivePopGestureRecognizer.enabled = YES;
        }
        else
        {
            self.interactivePopGestureRecognizer.enabled = NO;
        }
    }
}
2020-07-07