3

我对此很陌生......提前抱歉。我在 xCode 中创建了一个包含 10 个视图控制器的应用程序。每个视图控制器都有一个图像视图和一个圆形矩形按钮。

我想对其进行设置,以便按下视图上的按钮将转到其他 9 个视图之一,但加载的视图需要是随机的。

到目前为止我所做的:

-我在情节提要上放置了 10 个视图控制器,并将每个视图控制器的类设置为场景 1-10

-我创建了 10 个名为 scene1-10 的 Objective-C 类视图控制器(.h 和 .m 文件)

-我在这个时尚场景1-->scene2-->scene3-->scene4-->scene5-->scene6-->7scene-->scene8-->scene9-->scene10-->中创建了它们之间的segues场景1

-我已经将每个segue的类设置为segue1-10,以他们要去的场景命名(scene1和scene2之间的segue是segue2)

-我让所有的.h文件看起来像这样(场景#根据文件而变化):

#import <UIKit/UIKit.h>

@interface scene1 : UIViewController

- (IBAction) randomButton;

@end

-我让所有的.m文件看起来像这样(场景#根据视图而变化

#import "scene1.h"

@interface scene1 ()

@end

@implementation scene1

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}
- (IBAction) randomButton : (id) sender
{
    int i = arc4random() % 10;
    if(i == 1)
    {
        [self performSegueWithIdentifier: @"segue1" 
                                  sender: self];
    }
    else if(i == 2)
    {
        [self performSegueWithIdentifier: @"segue2" 
                              sender: self];
    }
    else if(i == 3)
    {
        [self performSegueWithIdentifier: @"segue3" 
                                  sender: self];
    }
    else if(i == 4)
    {
        [self performSegueWithIdentifier: @"segue4" 
                                  sender: self];
    }
    else if(i == 5)
    {
        [self performSegueWithIdentifier: @"segue5" 
                                  sender: self];
    }
    else if(i == 6)
    {
        [self performSegueWithIdentifier: @"segue6" 
                                  sender: self];
    }
    else if(i == 7)
    {
        [self performSegueWithIdentifier: @"segue7" 
                                  sender: self];
    }
    else if(i == 8)
    {
        [self performSegueWithIdentifier: @"segue8" 
                                  sender: self];
    }
    else if(i == 9)
    {
        [self performSegueWithIdentifier: @"segue9" 
                                  sender: self];
    }
    else
    {
        [self performSegueWithIdentifier: @"segue10" 
                                  sender: self];
    }
}
- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

@end

-我将每个视图控制器列出的接收到的动作“randomButton”链接到视图控制器上的按钮

怎么了:

我在每个 .m 文件的“@implementation scene1”行上收到“不完整的实现”警告,但该应用程序确实构建和加载。

一旦加载,如果我按下按钮,应用程序就会冻结,xCode 的调试窗口会弹出以下内容:

2012-05-05 07:11:11.789 randomTester[2448:f803] -[scene1 randomButton]: unrecognized                     selector sent to instance 0x686d370
2012-05-05 07:11:11.792 randomTester[2448:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[scene1 randomButton]: unrecognized selector sent to instance 0x686d370'
*** First throw call stack:
(0x13cc022 0x155dcd6 0x13cdcbd 0x1332ed0 0x1332cb2 0x13cde99 0x1914e 0x190e6 0xbfade 0xbffa7 0xbed8a 0x3e2cf 0x3e5e6 0x24dc4 0x18634 0x12b6ef5 0x13a0195 0x1304ff2 0x13038da 0x1302d84 0x1302c9b 0x12b57d8 0x12b588a 0x16626 0x1f5d 0x1ec5)
terminate called throwing an exception(lldb)

我意识到我可能做错了。我已经搜索了所有内容,但找不到我需要的确切内容,因此我不得不将类似代码中的部分拼凑在一起。

感谢您宝贵的时间和帮助!



更新

好的,第二轮:

你们太棒了,我完全没有意识到我已经通过 IBAction 的声明和实施做到了这一点。这修复了所有实施错误。但是,我似乎有一个潜在的问题。

我的 .h 文件现在看起来像这样:

#import <UIKit/UIKit.h>

@interface scene1 : UIViewController

- (IBAction) randomButton;

@end

我的 .m 苍蝇现在看起来像这样:

#import "scene1.h"

@interface scene1 ()

@end

@implementation scene1

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)randomButton
{
    int i = arc4random() % 10 + 1;
    NSString *segueIdentifier = [NSString stringWithFormat:@"segue%d", i];
    [self performSegueWithIdentifier:segueIdentifier sender:self];

}- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

@end

没有实现错误,它构建得很好,但是当我按下按钮加载时,应用程序会冻结,并且 xCode 的调试窗口会弹出以下内容:

2012-05-05 13:00:09.236 randomTester[2699:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:     'Receiver (<scene1: 0x6868f90>) has no segue with identifier 'segue5''
*** First throw call stack:
(0x13cb022 0x155ccd6 0xdd61b 0x2592 0x13cce99 0x1814e 0x180e6 0xbeade 0xbefa7 0xbdd8a 0x3d2cf 0x3d5e6 0x23dc4 0x17634 0x12b5ef5     0x139f195 0x1303ff2 0x13028da 0x1301d84 0x1301c9b 0x12b47d8 0x12b488a 0x15626 0x224d 0x21b5)
terminate called throwing an exception(lldb) 

很明显,应用程序正在查看scene1 视图控制器并且没有看到“segue5”(这是新的IBAction 调用的随机segue)。这是因为scene1视图控制器上没有segue5,因为它只有一个segue去scene2,如我上面问题的第一部分所述。

为了尝试解决这个问题,我在 scene1 上创建了 10 个 segue1-10 类。我将 segues 2-10 分别连接到场景 2-10。按钮可以调用 segue1 似乎是合乎逻辑的,因为它是随机的,因此指向自身。由于我无法创建从场景 1 到场景 1 的转场,因此我创建了到场景 2 的第二个转场,并且只给了它一个 segue1 类。

没有错误并且应用程序加载但点击按钮导致应用程序冻结这次在调试中显示:

2012-05-05 13:45:04.467 randomTester[2803:f803] -[scene1 randomButton:]: unrecognized selector sent to instance 0x68b3760
2012-05-05 13:45:04.479 randomTester[2803:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:     '-[scene1 randomButton:]: unrecognized selector sent to instance 0x68b3760'
*** First throw call stack:
(0x13cb022 0x155ccd6 0x13cccbd 0x1331ed0 0x1331cb2 0x13cce99 0x1814e 0x180e6 0xbeade 0xbefa7 0xbdd8a 0x3d2cf 0x3d5e6 0x23dc4     0x17634 0x12b5ef5 0x139f195 0x1303ff2 0x13028da 0x1301d84 0x1301c9b 0x12b47d8 0x12b488a 0x15626 0x224d 0x21b5)
terminate called throwing an exception(lldb) 

问题一: 任何想法需要如何设置这些 segues 才能使这项工作?

问题二: 会不会更好:

- 创建 10 个名为 scene1-10 的视图控制器,每个控制器都有一个图像视图和一个按钮

-将每次启动segue的按钮设置为名为sceneRandomizer的第11个视图控制器(我不会给这些segues类)

- 连接从 sceneRandomizer 回到场景 1-10 的 10 个 segue(类将是 segue1-10)

- 在“sceneRandomizer”中编写代码以自动从 1-10
组中启动随机序列,非常类似于重定向(我不知道如何编写......只是把它扔在那里)

从理论上讲,这将减轻我遇到的第二个错误,即调用它的视图控制器上不存在调用的 segue。

如果这种替代设置可行,它会产生从一个转场到另一个转场的任何重大滞后吗?




更新

现在正在工作

终于让这个工作了。这似乎是一种“迂回”的方法,我相信有一种更有效和更可接受的方法来做到这一点,但这就是我所做的:

.h 和 .m 中的代码与上次尝试的代码相同,但我将重申它只是为了清楚:

我的 .h 文件如下所示:

#import <UIKit/UIKit.h>

@interface scene1 : UIViewController

- (IBAction) randomButton;

@end

我的 .m 文件如下所示:

#import "scene1.h"

@interface scene1 ()

@end

@implementation scene1

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)randomButton
{
    int i = arc4random() % 10 + 1;
    NSString *segueIdentifier = [NSString stringWithFormat:@"segue%d", i];
    [self performSegueWithIdentifier:segueIdentifier sender:self];

}- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

@end

我做的不同:

好的,这次我将 11 个视图控制器拖到情节提要上

  • 我将一个命名为“startPage”并将其他命名为“scene1-10”

  • 我创建了 1 个 .h 和一个 .m 文件(编码如上所示)并将它们命名为 StartPage.h 和
    StartPage.m

  • 我将故事板上的所有 11 个视图类设置为一个视图控制器(StartPage)

  • 我做了10个segues,1个从StartPage到10个场景中的每一个

  • 我从场景 1 制作了 10 个转场,从场景 1 到其他 9 个场景中的每一个,并给了他们 segue2-10 的类(以他们去的场景命名)
    注意
    因为我无法创建从场景 1 到场景 1 的转场,所以我从scene1到scene2进行了第二次segue,并简单地给它一个segue1类。

  • 我为其他 9 个场景重复了最后一步

这确实有效。它构建并运行没有错误。StartPage 首先出现。点击按钮将加载组中的随机视图(场景 1-10),点击结果视图上的按钮将随机加载组中的另一个视图,依此类推。

这样做的不利方面是设置所有转场所需的时间。这个故事板现在有 110 个 segue,控制仅 11 个视图之间的移动。.....那是我生命中的一个小时,我再也回不去了。

对于像我这样的新手:

如果您选择使用此方法,在命名您的 segue 标识符时要非常小心。假设您为场景 5 布置了 segues,并且您错误地将 2 个 segues 命名为 segue2,而忘记命名一个 segue3。如果最终用户在scene5 并且随机按钮调用segue3,则应用程序将崩溃,因为scene5 没有名为segue3 的segue。我只提到这一点是因为在测试过程中很难发现这样的错误,因为一切看起来都很好,除非你在场景 5 时碰巧调用了 segue3。

如果有人发现使用这种方法有任何我不知道的缺点,请提出来。如果你有更好的方法,我会全力以赴:)

4

3 回答 3

2

错误和编译器警告告诉你,即使你说你实现了 randomButton 但实际上并没有。

您正在实施

-(void)randomButton:(id)sender;这与-(void)randomButton;

两个不同的签名。让任何一方匹配另一方,它应该工作。

于 2012-05-05T12:41:24.970 回答
1

方法的声明和实现randomButton应该具有相同的签名。.h所以,你应该在文件中这样声明它:

- (IBAction)randomButton:(id)sender;

像这样在.m文件中更改它:

- (IBAction)randomButton
{
    int i = arc4random() % 10;
    // ...
}

作为旁注,您可以通过使用以下值生成 segue 标识符来简化代码i

- (IBAction)randomButton
{
    int i = arc4random() % 10 + 1;
    NSString *segueIdentifier = [NSString stringWithFormat:@"segue%d", i];
    [self performSegueWithIdentifier:segueIdentifier sender:self];
}

另外,请注意,我将i生成值的行从1更改为10。您的原始代码产生从0to 的值9

于 2012-05-05T12:40:25.023 回答
0

我曾经使用来自单亲的模态视图控制器来做这样的事情。按下按钮会告诉 parentView dismissModalViewController,然后在 parent 的 viewWillAppear 中,生成一个随机数并 pushModalViewController。我用 xibs 完成了这一切,所以我不确定你将如何使用模态 segues 来处理它。如果你弄清楚了,请告诉我们。

于 2012-05-06T22:07:52.980 回答