2012-03-12 106 views
191

我有一个共同的UIViewController我所有的UIViewsControllers延长重用一些常用的操作。创建赛格瑞编程

我想在此“常用”UIViewController上设置一个继续,以便继承所有其他UIViewControllers

我想弄清楚如何以编程方式做到这一点。

我想这个问题也可以是如何为所有我的UIViewControllers设置一个segue而无需进入故事板并手动完成。

回答

157

根据定义,赛格瑞不能真正独立存在的一个故事板。它甚至还以班级的名字:UIStoryboardSegue。您不会以编程方式创建赛格 - 它是为您创建它们的Storyboard运行时。您通常可以在视图控制器的代码中调用performSegueWithIdentifier:,但这依赖于已经在故事板中设置了一个segue来引用。

我想你是问,虽然是你如何创造你的普通视图控制器(基类),将过渡到一个新的视图控制器的方法,并且将由所有派生类继承。您可以通过创建类似这样的方法来你的基类视图控制器做到这一点:

- (IBAction)pushMyNewViewController 
{ 
    MyNewViewController *myNewVC = [[MyNewViewController alloc] init]; 

    // do any setup you need for myNewVC 

    [self presentModalViewController:myNewVC animated:YES]; 
} 

,然后在派生类中,调用该方法被点击相应的按钮或选择表行或什么的。

+3

感谢。我们无法通过编程来实现这一点令人遗憾。这确实会提高源代码的质量(减少重复总是很好)。我会和你的建议一起去。 – 2012-03-13 08:37:05

+1

有些情况下无法从IB创建赛段,例如:如果我想绑定mapview注释的公开按钮,则在设计时我没有任何项目要在IB中拖动。无论如何,事实是“我们不能”,所以让我们手动完成。 – kappa 2012-03-16 11:19:18

+2

@jonkroll是否可以从switch语句调用/执行segue,即基于我拥有的索引? – codejunkie 2012-04-14 10:57:47

44

想这是回答和接受,但我只是想更多的一些细节添加到它。

我做了什么来解决一个问题,我将提出一个登录视图作为第一个画面,然后想Segue公司的应用程序,如果登录是正确的。我创建了从登录视图控制器到根视图控制器的segue,并给它一个标识符,如“myidentifier”。

然后检查所有登录代码,如果登录是正确的后,我会打电话给

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

我最大的误解是,我试图把SEGUE上的按钮和种中断SEGUE一旦被发现。

+4

正如我写的另一个评论:我一直在编程创建和执行自定义赛格(请参阅我的答案)。 – 2013-07-05 13:08:31

+0

伟大的回应!谢谢! – 2013-07-25 17:47:50

31

你有你的代码链接到您正在使用的UIStoryboard。确保你进入YourViewControllerUIStoryboard,点击它周围的边框,然后将其identifier字段设置为您在代码中调用一个NSString

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" 
                bundle:nil]; 
YourViewController *yourViewController = 
(YourViewController *) 
    [storyboard instantiateViewControllerWithIdentifier:@"yourViewControllerID"]; 
[self.navigationController pushViewController:yourViewController animated:YES]; 
+1

我得到这个,但是如果我想呈现的viewController嵌入在故事板的NavigationController中呢?从我所能找到的,我可以初始化一个NavigationController嵌入它,但在故事板,我已经推动塞格设置视图需要提交。 – jhilgert00 2012-12-14 02:11:02

+1

你能详细解释一下吗?我认为这是我遇到的问题,但似乎无法找到如何/在哪里做... – 2013-07-14 00:00:35

+1

即使这种解决方案是正确的,它是关于避免任何赛格,但问题是关于赛格。通过这种方式,您可以连接或在两个场景之间进行切换,而无需在故事板中继续播放。 – BootMaker 2016-10-17 13:06:06

15

对于故事板中的控制器。

jhilgert00这就是你要找的东西?

-(IBAction)nav_goHome:(id)sender { 
UIViewController *myController = [self.storyboard instantiateViewControllerWithIdentifier:@"HomeController"]; 
[self.navigationController pushViewController: myController animated:YES]; 

} 

或者......

[self performSegueWithIdentifier:@"loginMainSegue" sender:self]; 
+0

工作致谢。 – 2014-04-26 16:21:06

+0

这一个工作! +1 – 2014-07-04 07:29:06

2

故事板塞格斯不被故事板之外创建的。尽管存在缺陷,您仍需要将其连接起来。

UIStoryboardSegue Reference明确规定:

不创建SEGUE直接对象。相反,故事板 运行时创建它们时,它必须在两个视图控制器之间执行循环。如果你需要 需要,你仍然可以使用performSegueWithIdentifier:sender:UIViewController的方法以编程方式启动一个segue。您可能会这样做,以编程方式添加 ,因此在Interface Builder中不可用,从而启动segue。

,您仍然可以以编程方式告诉故事板呈现使用使用presentModalViewController:pushViewController:animated:呼叫赛格瑞视图控制器,但你需要一个故事板实例。

您可以通过调用UIStoryboard的s类方法来获取一个命名故事板,该包含主包的零套件。

storyboardWithName:bundle:

78

我一直在使用这个代码来实例化我的自定义赛格瑞子类,编程运行它。它似乎工作。这有什么问题吗?我感到困惑,阅读所有其他答案,说它无法完成。

UIViewController *toViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"OtherViewControllerId"]; 
MyCustomSegue *segue = [[MyCustomSegue alloc] initWithIdentifier:@"" source:self destination:toViewController]; 
[self prepareForSegue:segue sender:sender]; 
[segue perform]; 
+4

MyCustomSegue中有什么? – 2013-06-15 23:50:39

+3

它是'UIStoryboardSegue'的一个自定义子类。 – 2013-06-16 08:52:16

+1

什么是发件人? – 2013-07-06 04:58:58

340

我以为我想补充另一种可能性。你可以做的一件事是你可以连接故事板中的两个场景,使用没有附加到动作的segue,然后以编程方式触发视图控制器内的segue。您这样做的方式是,您必须从故事板场景底部的文件所有者图标(即继续播放场景)中拖动,然后右拖到目标场景。我会投入一个图像来帮助解释。

enter image description here

弹出框将显示为 “手动Segue公司”。我选择了Push作为类型。点击小方块,确保你在属性检查器中。给它一个你将用来在代码中引用它的标识符。

enter image description here

确定,下一步我打算使用编程栏按钮项目Segue公司。在viewDidLoad中或其他地方,我会用这个代码在导航栏上创建一个按钮项:

UIBarButtonItem *buttonizeButton = [[UIBarButtonItem alloc] initWithTitle:@"Buttonize" 
                    style:UIBarButtonItemStyleDone 
                    target:self 
                    action:@selector(buttonizeButtonTap:)]; 
self.navigationItem.rightBarButtonItems = @[buttonizeButton]; 

好,注意选择是buttonizeButtonTap :.所以写该按钮的无效方法和方法中,你将调用SEGUE这样的:需要

-(void)buttonizeButtonTap:(id)sender{ 
    [self performSegueWithIdentifier:@"Associate" sender:sender]; 
    } 

sender参数来识别按钮时prepareForSegue被调用。 prepareForSegue是一个框架方法,你可以实例化你的场景并传递它需要做的任何值。以下是我的方法:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:@"Associate"]) 
    { 
     TranslationQuizAssociateVC *translationQuizAssociateVC = [segue destinationViewController]; 
     translationQuizAssociateVC.nodeID = self.nodeID; //--pass nodeID from ViewNodeViewController 
     translationQuizAssociateVC.contentID = self.contentID; 
     translationQuizAssociateVC.index = self.index; 
     translationQuizAssociateVC.content = self.content; 
    } 
} 

好的,只是测试它,它的工作原理。希望它可以帮助你。

+0

@MichaelRowe这是如何消除对segues的需求?正如我看到它,你仍然必须拖放到故事板到目的地控制器.. – aherrick 2014-03-26 23:08:08

+0

@MichaelRowe这并不能消除对segues的需要。这样做可以让你在代码中而不是在界面构建器中构建的视图控制器之间延续。 – Matthew 2014-04-29 10:49:00

+0

@Matt它实际上只是让我完全重新思考我如何设置我的应用程序......在完全重写所有的UI后,我不再使用任何segues .. – 2014-05-11 20:47:25

0

一对夫妇的问题,实际上是:

首先,在您上传的我们的项目中,SEGUE不承担“segue1”标识符:

没有标识

您应该填写那个标识符,如果你还没有。

其次,当您从表视图推送到表视图时,您调用initWithNibName来创建视图控制器。你真的想使用instantiateViewControllerWithIdentifier。

3

我想补充澄清...

一个常见的误解,其实一个,我已经有一段时间,是一个故事板赛格瑞由prepareForSegue:sender:方法所触发。不是这样。无论您是否为该视图控制器实施了prepareForSegue:sender:方法,故事板segue都会执行。

我从Paul Hegarty的优秀iTunesU lectures了解到这一点。我的歉意,但不幸的是不记得哪一次讲座。

如果你在故事板连接两个视图控制器之间的SEGUE,但没有实现prepareForSegue:sender:法,SEGUE仍将Segue公司的目标视图控制器。然而,它会继续对该视图控制器毫无准备。

希望这会有所帮助。

1

我逆向工程并取得一个开源(重新)执行UIStoryboard的塞格斯的:https://github.com/acoomans/Segway

与该库,您可以通过编程定义塞格斯(没有任何故事板)。

希望它可以帮助。

2

首先,假设你在故事板两种不同的看法,并且希望从一个屏幕导航到另一位置,所以按照此步骤:

1)。使用类文件定义所有视图,并在身份检查器中定义storyboard ID。 2)。确保您将导航控制器添加到第一个视图。在故事板中选择它,然后选择编辑器>嵌入>导航控制器

3)。在你的第一类,导入 “secondClass.h”

#import "ViewController.h 
#import "secondController.h" 

4)。在IBAction中添加该命令必须执行该阶段

secondController *next=[self.storyboard instantiateViewControllerWithIdentifier:@"second"]; 
[self.navigationController pushViewController:next animated:YES]; 

5)。 @"second"是secondview控制器类,故事板ID。

+0

'self.storyboard'应该是:'UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@“MainStoryboard”bundle:nil];' – masipcat 2017-03-15 16:00:02

+0

@masipcat和故事板名称可能取决于你如何设置你的Xcode项目,在我的是“Main.storyboard”,所以我用'storyboardWithName:@“Main”' – ammianus 2017-09-10 19:50:56

+0

@ sanket-chauhan如果你的第一个控制器没有嵌入导航控制器,你也可以使用'[self showDetailViewController:next sender:self];'或'[self showViewController:next sender:self]显示下一个视图;' – ammianus 2017-09-10 19:52:00

0

这里是Creating a segue programmatically代码示例:

class ViewController: UIViewController { 
    ... 
    // 1. Define the Segue 
    private var commonSegue: UIStoryboardSegue! 
    ... 
    override func viewDidLoad() { 
     ... 
     // 2. Initialize the Segue 
     self.commonSegue = UIStoryboardSegue(identifier: "CommonSegue", source: ..., destination: ...) { 
      self.commonSegue.source.showDetailViewController(self.commonSegue.destination, sender: self) 
     } 
     ... 
    } 
    ... 
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     // 4. Prepare to perform the Segue 
     if self.commonSegue == segue { 
      ... 
     } 
     ... 
    } 
    ... 
    func actionFunction() { 
     // 3. Perform the Segue 
     self.prepare(for: self.commonSegue, sender: self) 
     self.commonSegue.perform() 
    } 
    ... 
} 
+0

您正在调用'self.prepare(for:self.commonSegue,sender:self )'从你的行动方法。那么在'prepare(for:sender)'方法中比较'self selfmonSegue == segue {...}'有什么意义呢? – nayem 2017-07-03 03:33:44

+0

@nayem:在'prepare(for:sender:)'中,你可以在目标视图控制器被显示之前进行配置。当然你也可以在'actionFunction'中做到这一点。 – jqgsninimo 2017-07-03 05:58:11

+0

@nayem:我这样做的原因是为了与其他赛段的处理保持一致。 – jqgsninimo 2017-07-03 06:10:51