设置 NavigationController.Viewcontrollers 崩溃(使用自定义转换)

Posted

技术标签:

【中文标题】设置 NavigationController.Viewcontrollers 崩溃(使用自定义转换)【英文标题】:Setting NavigationController.Viewcontrollers crashing (with custom transitions) 【发布时间】:2015-01-17 01:43:48 【问题描述】:

这是我的视图控制器层次结构:

-RootVC
 -MapVC
  -VC0
  -VC1
  -VC2

应用程序首先将@[Root, MapVC] 推送到视图控制器——一切都很好。 然后,我的目标是在四个主要 VC(MapVC、VC0、VC1、VC2)之间切换时加载地图(因此,我不想弹出 MapVC)。

为此,我使用以下代码:

   -(void)presentViewController:(NSString*)viewControllerIdentifier
    UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:viewControllerIdentifier];

    if (![[self.navigationController.viewControllers objectAtIndex:[[self.navigationController viewControllers] count]-1] isKindOfClass:[vc class]])

        NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:[[self navigationController] viewControllers]];
        if (![[viewControllers lastObject] isKindOfClass:[LLMapViewController class]]) 
        [viewControllers removeLastObject];
        
        [viewControllers addObject:vc];
        [[self navigationController] setViewControllers:viewControllers animated:YES];
        


-(void)presentViewController0:(NSNotification*)notif
        [self presentViewController:[notif name]];

-- 地图呈现方式:

-(void)presentMapViewController:(NSNotification*)notif
    if (![[self.navigationController.viewControllers objectAtIndex:[[self.navigationController viewControllers] count]-1] isKindOfClass:[LLMapViewController class]])
        [self.navigationController popViewControllerAnimated:YES];
    

好吧,如果我不对这个过渡进行动画处理,它会很好地工作。 此外,当我执行以下操作时,一切正常

App Launches:
->Root 
 ->MapVC

ACTIONS: 
0: Select VC0
->Root
 ->MapVC
  ->VC0

1: Select VC1 (Pops VC0 and pushes VC1, as you can see in the code above)
->Root
 ->MapVC
  ->VC1

2: Select MapVC (Pops VC1)
->Root
 ->MapVC

问题是当我尝试推送另一个以 MapVC 作为主 VC 的 VC 时:

3: Select VC0
->Root
 ->Map
....

崩溃!

它没有显示任何一致的错误。 有时它不显示任何错误,有时它显示如下错误:

Example 1: 
-[NSLayoutConstraint navigationController:animationControllerForOperation:fromViewController:toViewController:]:

Example 2: 
-[UILabel navigationController:animationControllerForOperation:fromViewController:toViewController:]:

但当我设置导航控制器的视图控制器时,它总是突出显示部分。

我的问题:我花了大约 8 个小时试图解决这个问题。我对如何调试这个没有更多的想法。 谁能帮助我吗?

附:我正在使用自定义转换来推送/弹出控制器。 这是附加代码:

-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC 

    LLMenuAnimation *animationController = [[LLMenuAnimation alloc] initWithNavigationController:self.navigationController];
    switch (operation) 
        case UINavigationControllerOperationPush:
            animationController.type = AnimationTypePush;
            return  animationController;
        case UINavigationControllerOperationPop:
            animationController.type = AnimationTypePop;
            return animationController;
        default:
            NSLog(@"OTHER OPERATION");
            return nil;

    


 

--

#pragma mark - Animated Transitioning

-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext 
    return 0.2;


-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext 
    //Get references to the view hierarchy
    UIView *containerView = [transitionContext containerView];
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    if (self.type == AnimationTypePush) 
        //Add 'to' view to the hierarchy with 0.5 scale

        toViewController.view.transform = CGAffineTransformMakeScale(0.5, 0.5);


        [containerView insertSubview:toViewController.view aboveSubview:fromViewController.view];

        //Scale the 'to' view to to its final position
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^
            //            toViewController.view.frame = fromViewController.view.frame;
            toViewController.view.transform = CGAffineTransformMakeScale(1.0, 1.0);

         completion:^(BOOL finished) 
            [transitionContext completeTransition:YES];
        ];
     else if (self.type == AnimationTypePop) 
        //Add 'to' view to the hierarchy
        [containerView insertSubview:toViewController.view belowSubview:fromViewController.view];

        //Scale the 'from' view down 
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^
            fromViewController.view.transform = CGAffineTransformMakeScale(0.5, 0.5);

         completion:^(BOOL finished) 
            [transitionContext completeTransition:YES];
        ];
    

【问题讨论】:

你能解释一下为什么你不想弹出 MapVC 吗?我也明白VC(VC1,2,3)可以直接互相访问? 因此地图不会多次加载/渲染。不,他们不能。我在根 vc 中有一个抽屉菜单 但是地图加载不止一次有什么问题? ios 会处理它,它会被“缓存”并在你下次展示这个 VC 时加载得更快。 可以,但对用户来说体验会更差 我认为@DaniA 可能会有所作为——看起来委托正在被解除分配,其他对象正在同一地址创建。您是否尝试过使用 Zombies 和/或记录委托的 dealloc 方法? 【参考方案1】:

我不相信您可以按照您尝试的方式使用 UINavigationController。如果我已经理解您要做什么,您想从导航控制器下方替换导航控制器的 viewControllers 属性。

顺便说一下,viewControllers 显示的属性是一个副本。这是documentation中定义的方式:

@property(nonatomic, copy) NSArray *viewControllers

您的代码:

        NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:[[self navigationController] viewControllers]];
    if (![[viewControllers lastObject] isKindOfClass:[LLMapViewController class]]) 
    [viewControllers removeLastObject];
    
    [viewControllers addObject:vc];
    [[self navigationController] setViewControllers:viewControllers animated:YES];
    

不会按您预期的方式工作。您可以将视图控制器推送和弹出到导航控制器上。您无法按照您尝试的方式替换 viewController。

顺便说一句,您在上述问题的前几行中绘制的视图控制器层次结构是不完整的。层次结构中的导航控制器在哪里?

【讨论】:

navigationcontroller的rootviewcontroller是RootVC。是的,我可以这样使用它。除了我认为与委托设置有关的崩溃之外,它工作得很好。还在努力解决 @jonypz,我认为你在这里遗漏了一些非常基本的东西。你上面的说法没有任何意义。您尚未在层次结构中显示任何导航控制器。如果您说 rootVC 是一个导航控制器,那么请准确地说出来并准确描述您的设置。另外,它怎么能完美地工作并且仍然崩溃?它不像你想象的那样工作。如果您的实现完全有效,那是偶然的,而不是因为它的正确性。我不会重复我在回答中所说的话;但是,我建议你仔细阅读。 导航控制器的关系segue“root”被定向到RootVC(RootVC是导航控制器的第一个控制器)。除了执行上述情况外,它工作得很好(如果我不执行这种情况一切都很好。) 如果你的 mapvc 已经推送到 navVC,为什么不将 VCx (VC0, VC1, ...) 推送到 navVC?您可以随时从 navVC 中弹出所有 Vcx 以显示 mapVC。您无法像在代码中尝试那样替换 viewControllers 属性。在尝试修改属性的代码执行时,您的导航控制器已经“活动”了。这不是正确的代码。这可能是您崩溃的原因。 你应该仔细阅读我上面写的(包括 cmets)。我可以使用 setviewcontroller 方法替换视图控制器,你试试看吧。

以上是关于设置 NavigationController.Viewcontrollers 崩溃(使用自定义转换)的主要内容,如果未能解决你的问题,请参考以下文章

短视频运营短视频剪辑 ⑤ ( 视频素材使用 | 设置插入后的视频素材属性 | 设置画面 | 设置音频 | 设置变速 | 设置动画 | 设置调节 )

SeeMusicMIDI 编辑功能 ( 速度设置 | SoundFont 音源设置 | 混响强度设置 | 混响时间设置 | 力度增益设置 | 实时 MIDI 设置 )

win10设置里的代理怎么设置

强制恢复出厂设置?

怎么设置标题样式?

HTMLHTML 注册表单案例 ① ( 表格设置 | 设置表格位置和大小 | 设置表格标题 | 表单设置 | 表格中设置单选按钮 )