无法触发 Segue 手动加载 VC - self.navigationController 为 Nil?

Posted

技术标签:

【中文标题】无法触发 Segue 手动加载 VC - self.navigationController 为 Nil?【英文标题】:Unable to trigger Segue to manually load VC - self.navigationController is Nil? 【发布时间】:2014-07-11 09:36:11 【问题描述】:

编辑

经过更多的挖掘,很明显,如果我在快速应用程序切换到/从 Safari 之后尝试从视图控制器类调用 segue,我会收到一个异常,指出 segue 不存在。确实如此,在屏幕上加载的 VC 中,我检查了拼写,它是 100% 正确的。

更奇怪的是,如果我从 IBAction 调用完全相同的方法,它就可以正常工作。

这是我正在使用的代码:

-(void)goToPhotoPage

    [self performSegueWithIdentifier:@"twitterAuthComplete" sender:self];


如果我在应用程序恢复时调用它,我会得到一个异常,但是如果我从这个 IBAction 调用它,附加到一个 UIButton,没有做任何不同的事情,segue 会按预期工作并且没有异常。

- (IBAction)twitterToPhoto:(id)sender

    [self goToPhotoPage];

Arrrrgrghrhhgrgrg!

原始问题

我正在开发一个将用户照片上传到 Facebook/Twitter 的 iPad 应用程序。

作为过程的一部分,我必须跳转到 Safari 为 twitter 执行 OAuth,然后应用程序通过特定 URL 跳转回来并获取令牌等

但是由于某种原因,当应用程序重新唤醒时,我无法触发任何 segue 或手动加载任何 VC。

我的 AppDelegae 中有一个成功块,当上传完成时会调用它,它会调用 VC 中的方法来关闭微调器并转到成功视图。

微调器按预期停止,但无论我尝试什么,我都无法让 segue 工作。

一切都已连接,segue 有一个 ID,我在控制台中没有收到任何错误或异常,只是没有任何反应。在这一点之后,我可以让代码触发的 segue 工作的唯一方法是使用用户触发器连接到 UIButton,完成后他们再次开始工作。

这是我的 AppDelegate 中带有回调的代码:

- (void)postToTwitter:(NSString*)postText image:(UIImage*)image
    
    NSData *data = UIImageJPEGRepresentation(image, 0.5);

    [_twitter postStatusUpdate:postText
                mediaDataArray:@[data]
             possiblySensitive:nil
             inReplyToStatusID:nil
                      latitude:nil
                     longitude:nil
                       placeID:nil
            displayCoordinates:nil
           uploadProgressBlock:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) 

            successBlock:^(NSDictionary *status) 

               ViewController * vc = [[ViewController alloc]init];
               [vc triggerSuccess];

            errorBlock:^(NSError *error) 

               ViewController * vc = [[ViewController alloc]init];
               [vc uploadFail:error];

           ];

在 VC 中我尝试了以下方法:

- (void)triggerSuccess
    
    [self segueToSuccess];


- (void)segueToSuccess
    
    [self hideMessage];
    [self.navigationController performSegueWithIdentifier:@"approveSegue" sender:self];    

还有:

- (void)triggerSuccess
    
    [self segueToSuccess];


- (void)segueToSuccess
    
    [self hideMessage];
    UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"done"];
    [self.navigationController pushViewController:controller animated:YES];

在绝望的时刻,我什至尝试过:

- (void)triggerSuccess
    
    [self segueToSuccess];


- (void)segueToSuccess
    
    [self hideMessage];
    //[self.navigationController performSegueWithIdentifier:@"approveSegue" sender:self];
    [self dismissViewControllerAnimated:NO completion:nil];
    [self.navigationController popToRootViewControllerAnimated:NO];
    [self performSelector:@selector(segueToSuccessPart2) withObject:nil afterDelay:0.25];


- (void)segueToSuccessPart2
    
    UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"done"];
    [self.navigationController pushViewController:controller animated:YES];

我显然错过了一些东西,我猜这与应用程序进入后台和 VC 从内存中“卸载”并需要重新启动有关,但我不知道从哪里开始用那个。

任何帮助将不胜感激,因为我即将把电脑扔出窗外。 .

谢谢

加雷斯

编辑 1

在进行更多故障排除后,似乎在 VC 中的此调用期间:

[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController popToRootViewControllerAnimated:NO];

self.navigationController 为 nil 。 . .

我猜这可能是我看到的问题的原因?

编辑 2

因此,正如 Kelin 所建议的,我正在努力确保保留导航控制器。

我在 AppDelegte 中做了以下操作:

@property (nonatomic, strong) UINavigationController *navController;

@synthesize navController;

但是当我尝试使用下面的代码从 VC 访问它时,它仍然是 nil 。 .

AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
UINavigationController *navController = appDelegate.navController;

[self dismissViewControllerAnimated:NO completion:nil];
[navController popToRootViewControllerAnimated:NO];

编辑 3

我也将它添加到 AppDelegate 中,这意味着 Navigation Controller 不再是 nil。但仍然没有任何反应。 . .

if (!self.navController)

    self.navController = [[UINavigationController alloc]initWithNibName:@"Main" bundle:nil];

【问题讨论】:

【参考方案1】:

问题是您尝试使用以编程方式创建的视图控制器从情节提要执行 segue。

你使用-performSegueWithIdentifier: sender: 完全错误。在这个方法中,“sender”是一个按钮,或者任何其他初始化 segue 的控件,但不是要推送的视图控制器。

通常使用故事板创建 segue。但是如果你真的需要手动创建它,调用:

 -[UIStoryboardSegue initWithIdentifier:source:destination:]

源和目标是视图控制器。

阅读:https://developer.apple.com/library/ios/recipes/xcode_help-interface_builder/articles-storyboard/StoryboardSegue.html 或者这个(关于自定义转场):

【讨论】:

您好 Kelin,感谢您的快速回复。需要明确的是,我在情节提要中手动创建了一个从 VC 到目标 VC 的 segue,并为其指定了一个标识符。有趣的是,我刚刚进行了一些故障排除,当我尝试弹出到 rootVC self.navigationController 似乎是 nil 时,我猜这是很多这些问题的根源? 可能是的,您是否在 AppDelegate 或其他地方强烈引用了您的导航控制器? 不,除了标准样板之外,我没有添加任何东西来保存导航控制器。 您需要在某处保持对导航控制器的强引用。在旧样板中,AppDelegate 中强烈引用了导航控制器。新项目使用故事板并且没有这样的属性。 您好 Kelin,非常感谢您的帮助。因此,如果我添加到我的 VC 类中,@property (strong, nonatomic) UINavigationController *navigationController;并合成它会完成这项工作。或者我是否需要将它传递给 AppDelegate,以便在卸载 VC 时不会将其删除?谢谢!【参考方案2】:

你不能同时关闭和弹出,你必须弹出或关闭视图控制器和

每个 ViewController 都有自己的 NavigationController,它默认指向您添加到 AppDelegate 的导航控制器。

所以,您也可以通过 self.navigationController 访问它(编辑 3)

还要检查你是否初始化了导航控制器 应用委托

self.navController = [[UINavigationController alloc] initWithRootViewController:firstVC];

【讨论】:

以上是关于无法触发 Segue 手动加载 VC - self.navigationController 为 Nil?的主要内容,如果未能解决你的问题,请参考以下文章

facebook登录后触发segue

Pan Segue 调用 viewDidLoad 循环

无法调用 tableViewController

在 watchOS 上以编程方式触发 segue

导航控制器中的更改顺序

Segue 动画无法完全正常工作