iOS 应用程序在 PushViewController 上冻结 [英] iOS App Freezes on PushViewController

查看:17
本文介绍了iOS 应用程序在 PushViewController 上冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My navigation controller intermittently will freeze on push. It seems to add the new view controller onto the stack, but the animation never takes place. I also have two other containers that hold view controllers on the screen, and I can interact with both of them just fine after the navigation controller freezes. The really interesting thing is if I try to push another view controller onto the navigation controller's stack, I noticed that there is an extra view controller on top of the stack (the view controller that I pushed initially that froze the navigation controller). So if I'm on the home screen (we'll call it VC-Home) and I try to push a new view (VC-1) and it freezes, then I try to push a new view (VC-2), this is what I see in the current stack before the push:

{ [VC-Home, VC-1] }

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

and after pushViewController is called, it remains the same; VC-2 is not added to the stack.

据我所知,导航控制器通过在动画开始之前使前一个视图控制器处于非活动状态来启动动画,但随后动画永远不会发生,使导航控制器处于冻结状态.

From what I can tell, the navigation controller starts the animation by making the previous view controller inactive before the animation begins, but then the animation never takes place, leaving the navigation controller in a frozen state.

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

I'm creating the new view controller from a storyboard by calling UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") so I don't think there's any issues there. I'm also not overriding pushViewController on the navigation bar. Some unique things about my app is that it is very high-res image heavy (using SDWebImage to manage that) and I always have three containers on the screen at once (one navigation controller, one view controller for search, and one interactive gutter/side/slideout menu).

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

CPU usage is low and memory usage is normal (steadily around 60-70MB on device when freezes occur).

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

Are there any ideas with what might be causing this or any debugging tips that could help me discover the real problem?

更新

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

There's no unique code for the UINavigationController since I'm just pushing using pushViewController(). Here's the code that calls it:

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

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

The ViewController that I pushed has the following code in 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 秒翻阅一次其内容(想想应用商店的顶部横幅).在这个冻结时,我注意到横幅处于动画中间.

I finally got it to freeze again. The app was in the background and I brought it back and tried pushing a view controller on the stack when it froze. I noticed an animation was taking place. I have a scrollview at the top of the page that pages through its content every 10 seconds (think of the app stores top banner). On this freeze, I noticed that the banner was mid-animation.

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

Here's the scrolling function from the my UIScrollView that gets called every 10 seconds:

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)
}

我不记得曾经因为动画/滚动发生而有过推停,但我可能是错的.

I don't recall ever having a push stop because of an animation/scroll taking place, but I could be wrong.

我也重新检查了堆栈,与上述相同的情况仍然是 [VC-Home, VC-1] 是堆栈并且 VC-2 没有被压入的情况.我还检查了 VC-1 的变量,所有内容都已加载(数据调用和图像加载).

I've also rechecked the stack and the same situation as described above is still the case where [VC-Home, VC-1] is the stack and VC-2 is not pushed on. I've also gone through VC-1's variables and everything has loaded (data calls and image loads).

更新 3

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

This is getting stranger by the second. I've overriden pushViewController so I can put a breakpoint in there and do some debugging based on Alessandro Ornano's response. If I push a view controller unsuccessfully, then send my app to the background, put a breakpoint into the pushViewController call, and bring the app back, the breakpoint is immediately hit a number of times. If I then continue past all the hits, the next view controller suddenly becomes visible and the last view controller I tried to push is now on the stack as the last view controller. This means that the one that I see is still disabled, which essentially puts me in the same position as before.

推荐答案

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

We have faced the same problem couple of weeks back. And for our problem we narrowed it down to left-edge pop gesture recogniser. You can try and check if you can reproduce this problem using below steps

  • 当下方没有视图控制器时尝试使用左边缘弹出手势(即在根视图控制器上,您的 VC-Home 控制器)
  • 在此之后尝试点击任何 UI 元素.

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

If you are able to reproduce the freeze, try disabling the interactivePopGestureRecognizer when the view controller stack have only one view controller.

请参阅这个问题了解更多详情.下面是链接中的代码,方便参考.

Refer to this question for more details. Below is the code from the link for ease of reference.

- (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;
        }
    }
}

这篇关于iOS 应用程序在 PushViewController 上冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆