3

我有一个项目,我在其中使用故事板、导航控制器和故事板 segues。我在其中一个视图中有一个 cocos2d 视图。该视图GameLayer具有CCLayer嵌入在 cocos2dViewController 中的类,cocos2dViewController : CCViewController而 CCViewController 又是 .so 的子类。CCViewController : UIViewController所以,在我的 Cocos2d 视图中,它是一个 CCLayer,不能使用 [self performSegue....] 方法,因为它不是uiviewcontroller 的直接子类或其他东西。

我试过了

    GameOverViewController *gameOver = [[GameOverViewController alloc]init];
    UIViewController* rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    [rootViewController presentViewController:gameOver animated:YES completion:NULL];

但这只是让我Warning: Attempt to present <GameOverViewController: 0x107d0060> on <UINavigationController: 0x9d33890> whose view is not in the window hierarchy!

我也试过

    GameOverViewController *gameOver = [[GameOverViewController alloc]init];
    AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
    [[app navController] presentModalViewController:gameOver animated:YES];

但这根本没有做任何事情

所以我要么需要在 UIViewController 的子类的较高类之一上执行选择器,在这种情况下,我该怎么做?

或者我需要从我的 CCLayer 执行 segue,在这种情况下我该怎么做?对我来说都很好:)

编辑:澄清的问题: 我需要从作为子类的 GameLayer 中进行转场CCLayer,因此它不能使用正常的转场方法。GameLayer 是嵌入的或其他的,cocos2dViewController它的子类CCViewController最终是 UIViewController 的子类。我在我的项目中使用故事板,CCViewController 是响应 IBOutlets 的视图控制器。所以我需要从我的游戏层以某种方式从这个文件中推送转场。您可以在此处查看游戏系统: mediafire.com/ ?7dil7uolo5k1syr ,来自我制作的模板。我想将一个 segue 从游戏视图控制器拉到另一个视图。到目前为止,我已经尝试了在另一个文件 ccdirector 和其他文件中执行此操作的各种方法。

对于不熟悉 cocos2d 的人来说,CCLayer 是 CCNode 的子类,CCNode 是 NSObject 的子类。因此,您可以将此视为有关如何从 NSObject 在 UIViewController 中执行 segue 的问题。

所以 tl;dr:从嵌入 UIViewController 子类的子类中的 CCLayer(NSObject) 执行故事板转场。

4

5 回答 5

1

好的,我想我得到了这个工作。我尝试了很多方法,主要问题是 GameLayer 是 CCLayer,很难找到包含它的 ViewController。

您需要参考 cocos2dViewController ViewController 来执行 segue,我的解决方案并不理想,但它在这种情况下有效。

我使用 NSNotificationCenter 从 GameLayer 发布通知,然后将 cocos2dViewController 控制器添加为观察者。当 cocos2dViewController 控制器收到通知时,您执行 segue

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

这些是确切的步骤:

  1. 将新的 View Controller 拖到 Storyboard
  2. 创建一个从 cocos2dViewController 到新创建的 ViewController 的 push segue 并将这个 segue Identifier: "segueFromCocos" 添加到 segue
  3. 将与 cocos2dViewController 的 segue 从 modal 更改为 push
  4. 在 init 方法中为 GameLayer 添加一个按钮:

    UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [nextButton setTitle:@"next" forState:UIControlStateNormal];
    nextButton.tag = 123;
    nextButton.frame = CGRectMake(10.0, 10.0, 90.0, 40.0);
    [nextButton addTarget:self
                   action:@selector(nextButtonClicked:)
         forControlEvents:UIControlEventTouchDown];
    
    UIView *glView = [CCDirector sharedDirector].view;
    [glView addSubview:nextButton];
    

    此按钮将在 nextButtonClicked: 选择器中推送通知

    • (void)nextButtonClicked:(id)sender { NSLog(@"通知发布"); [[NSNotificationCenter defaultCenter] postNotificationName:@"TestNotification" object:self]; }
  5. 然后在 cocos2dViewController 视图控制器的 viewDidLoad 方法中注册 cocos2dViewController 作为观察者:

    [[NSNotificationCenter defaultCenter] addObserver:self 选择器:@selector(receiveTestNotification:) name:@"TestNotification" object:nil];

  6. 然后最后在 receiveTestNotification: 中执行 segue:

    • (void)receiveTestNotification:(NSNotification *) notification { if ([[notification name] isEqualToString:@"TestNotification"]) { NSLog (@"成功收到测试通知!%@", [self class]);

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

      } }

对不起,顺便说一句代码格式问题:)

更新 - 没有通知中心

我更改了代码并使其在没有通知的情况下工作。问题是获取 cocos2dViewController ViewController 的引用,以便您可以从那里执行 segue。

您首先需要获取对作为 UINavigationController 的 rootViewController 的引用,然后您只需从导航/根视图控制器中获取最后一个控制器:

[navC.viewControllers lastObject];

这是触摸下一个按钮时运行的代码:

UIViewController *root = [[[UIApplication sharedApplication] delegate] window].rootViewController;
if ( [root isKindOfClass:[UINavigationController class]] ) {
    UINavigationController *navC = (UINavigationController *)root;
    cocos2dViewController *cocosVC = (cocos2dViewController *)[navC.viewControllers lastObject];
    [cocosVC performSelector:@selector(asdf)];
}

然后在 cocos2dViewController 中你有 asdf 选择器,它只是执行 segue:

- (void)asdf
{
    [self performSegueWithIdentifier:@"segueFromCocos" sender:self];
}
于 2013-08-22T08:33:35.587 回答
1

如果您不想使用通知,请按以下步骤操作:

我更改了代码并使其在没有通知的情况下工作。问题是获取 cocos2dViewController ViewController 的引用,以便您可以从那里执行 segue。

您首先需要获取对作为 UINavigationController 的 rootViewController 的引用,然后您只需从导航/根视图控制器中获取最后一个控制器:

[navC.viewControllers lastObject];

这是触摸下一个按钮时运行的代码:

UIViewController *root = [[[UIApplication sharedApplication] delegate] window].rootViewController;
if ( [root isKindOfClass:[UINavigationController class]] ) {
    UINavigationController *navC = (UINavigationController *)root;
    cocos2dViewController *cocosVC = (cocos2dViewController *)[navC.viewControllers lastObject];
    [cocosVC performSelector:@selector(asdf)];
}

然后在 cocos2dViewController 中你有 asdf 选择器,它只是执行 segue:

- (void)asdf
{
    [self performSegueWithIdentifier:@"segueFromCocos" sender:self];
}
于 2013-08-23T10:20:29.843 回答
0

我不建议segues在使用Cocos2d. 相反,您应该将您的游戏结束屏幕显示为一个全新的CCScene,或者作为一个CCLayer,将其添加为您 parent 的子项CCNode。如果您的游戏结束屏幕是某种弹出/对话框,您也可以尝试CCLayerColor使用透明的黑色背景颜色。

于 2013-08-19T11:12:00.500 回答
0
GameOverViewController *gameOver = [self.storyboard instantiateViewControllerWithIdentifier:@"GameOverViewController"];
UINavigationController  *navController=[[UINavigationController new]initWithRootViewController:gameOver];
[self.navigationController presentViewController:navController animated:YES completion:Nil];

您应该尝试下面显示相同错误的链接——警告:尝试呈现:0xab5d9d0,其视图不在窗口层次结构中! 谁的视图不在窗口层次结构问题中

于 2013-08-19T14:24:07.407 回答
0

我完全同意 ssantos 和他们的解决方案,但如果你坚持尝试将 UIKit 和 cocos2D 混合在一起:

而不是“[self performSegue....]方法”,尝试,[[CCDirector sharedDirector] performSegue....]因为导演是 UIViewController 的子类。

我不能确定这是否会起作用,因为您以非常规的方式使用 cocos2D。


另一个观察:

您说您GameLayer的嵌入在cocos2dViewController.. 中是否引用了该视图控制器?你能打电话performSegue给那个吗?

于 2013-08-20T10:31:21.870 回答