如何在不需要segue的情况下编写代码调用故事板场景?

44

我有一个模态的故事板场景,我希望所有其他场景都可以访问它。从我的故事板上的每个场景创建模态segue会导致字符串到处乱飞的混乱。有没有一种方法可以不使用segue而是通过编程来调用该场景?

基本上我想要做这样的事情:

  MyNewViewController *myNewVC = [[MyNewViewController alloc] init];
  [self presentModalViewController:myNewVC animated:YES];

我希望使用模态过渡到一个“隔离”的(不连接任何segue)故事板场景,而不是创建并推送视图控制器类。

8个回答

87

可以的。像这样做一些事情来访问VC,然后只需模态推它:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];
MyNewViewController *myVC = (MyNewViewController *)[storyboard instantiateViewControllerWithIdentifier:@"myViewCont"];

这会将场景推送为模态视图吗(就像使用模态转换一样)? - zakdances
1
这取决于你如何展示它。使用[self presentModalViewController:myVC animated:YES]; 就可以了。 - Darren
谢谢。有一件事让我困惑...在第二行之后但在“presentModalViewController:myVC”行之前,我的VC会发生什么?它只是隐藏在后台吗? - zakdances
不要创建 MyNewViewController *myVC,而是创建 UINavigationController *myNav。确保给它一个可调用的标识符。 - Darren
你也可以使用self.storyboard获取当前故事板的引用。 - Alex Zavatone
显示剩余2条评论

40

注意:在iOS 6中,方法 presentModalViewController:animated 已被弃用。

新代码应该改为:

NSString * storyboardName = @"MainStoryboard_iPhone";
NSString * viewControllerID = @"ViewID";
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
MyViewController * controller = (MyViewController *)[storyboard instantiateViewControllerWithIdentifier:viewControllerID];
[self presentViewController:controller animated:YES completion:nil];

如果您想确保使用相同的故事板,也可以使用self.storyboard。 - Alex Zavatone
第一行需要稍微详细解释一下。虽然 presentModalViewController:animated 方法已经被标记为过时,但是现在可以使用 presentViewController:animated 作为替代方法,去掉方法名中间的 Modal 即可。对于初学者来说可能不太清楚,因为这两个方法调用看起来非常相似。 - Alex Zavatone

19
在Storyboard中给你的视图控制器添加标识符(在属性检查器下),然后使用以下代码将该视图带到前台。
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"STORYBOARDNAME" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:@"VIEWCONTROLLERIDENTIFIER"];
[self presentModalViewController:vc animated:YES];

1
当从AppDelegate中调用时,这似乎不起作用。 - radven
@radven,ViewControllers及其类无法从AppDelegate(我认为...)调用。 - Sam Spencer
1
@RazorSharp 真的吗? 我经常在AppDelegate中打电话给VC(如有需要)。例如(从我的脑海中跳出),当设置根标签栏控制器并且需要初始化选项卡中的视图控制器时。现在,为了使事物显示,您需要在App Delegate的呈现根视图控制器/故事板等方面进行操作。 - chadbag

6

我有一个案例,我想从应用程序的主要部分呈现一个视图控制器,其中包括设置和帮助等。为此,我希望它在导航控制器内,就像一个小插件模块,我们可以从UIBarButtonItem调用它。

现在,这可以是在当前故事板中进行,也可以是在另一个故事板中进行,这并不重要。

我想以这种方式做,因为我讨厌我的故事板上到处都是可能存在的segue线条混乱。

以下是如何实现的方法。

- (IBAction)displaySettings:(id)sender
{
    LOG_SELECTOR() // google that for extra goodness

    // FYI, this can be done using a different storyboard like so.
    /*
     NSString * storyboardName = @"MainStoryboard_iPhone"; // possibly use device idiom?
     UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
     */

    // To push a new set of scenes with a new Navigation Controller, it is done like this:
    UINavigationController *settingsNC = [self.storyboard instantiateViewControllerWithIdentifier:@"Settings Nav Controller"];
    OBSettingsUIViewController *settingsVC = [self.storyboard instantiateViewControllerWithIdentifier:@"Settings root"];
    [settingsNC pushViewController:settingsVC animated:NO];

    [settingsNC setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];

    // Present the view controller;
    [self presentViewController:settingsNC animated:YES completion:NULL];
}

在呈现的视图控制器中(或导航控制器的子类中),您可以添加一个UIBarButtonItem来关闭整个呈现的视图控制器层次结构,方法如下:
- (IBAction)dismissThisVC:(id)sender {
     [self dismissViewControllerAnimated:YES completion:nil];
}

希望这能帮助很多人,干杯。

4
只需使用导航控制器调用视图控制器。将以下代码写入视图控制器,并按照图片中所示设置故事板中的视图控制器。

enter image description here

ProfileVC *vc = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"ProfileVC"];
[self.navigationController pushViewController:vc animated:YES];

3

调用以导航到其他类

UIWindow *window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];

UINavigationController *navController = (UINavigationController *)window.rootViewController;

DumpFeed *dump = [storyboard instantiateViewControllerWithIdentifier:@"DumpFeed"];

dump.isPushed=YES;

dump.strUserId = appDelegate.strFriendid;


[navController pushViewController:dump animated:YES];

3
这是一个Swift版本的代码:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myVC = storyboard.instantiateViewControllerWithIdentifier("myStoryId")
self.presentViewController(myVC, animated: true, completion: nil)

您还应该像这样更改您的故事板ID: enter image description here

1

我认为使用iOS7,通过Storyboard实现变得非常容易。

我目前正在学习iOS7的新功能,并发现了这个简单的解决方案,但它可能在之前的版本中也是相关的,我不确定。

首先,您需要将呈现VC与目标VC连接(这是唯一需要的连接),然后在Storyboard的属性检查器中选择样式为modal,在身份检查器中为您的VC提供storyboardID,并确保您选中了“使用storyboardID”复选框,

如果还没有,请将此方法添加到您的presentingVC中:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

   YourTargetVC * targetVC = 
         (YourTargetVC *)segue.destinationViewController;

   if(nil != targetVC) {

       //Do preparations here
   }

}

现在,当您希望从您的 presentingVC 显示您的 targetVC 时,您可以使用以下代码:
[self performSegueWithIdentifier:(NSString *) sender:(id)];

当标识符为你的视图控制器的storyboardID,发送者是触发操作的视图时,此方法将调用storyboards场景,因此[prepareForSegue: sender:]方法将被调用,允许你在目标视图控制器出现之前进行最后修改。

3
“不需要转换话题”,因为“故事板会在各个地方创建一大堆字符串,让一切变得混乱不清”。 - Cœur
谢谢,你是正确的。但我认为原始问题是在iOS7发布之前发布的。 - supergegs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接