我如何从SKScene展示一个UIViewController?

我正在通过Sprite Kit进入iOS,我认识到这是不明智的。

我的目标是在游戏结束后显示“分享”button。 点击分享button应呈现一个SLComposeViewController(Twitter的份额)。 现场的内容不应该改变。

指示“Game Over”的游戏逻辑位于SKScene的子类SpriteMyScene.m中。

我可以在游戏上显示Sharebutton

-(void)update:(CFTimeInterval)currentTime { if (gameOver){ UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [button addTarget:self action:@selector(sendToController) forControlEvents:UIControlEventTouchDown]; [button setTitle:@"Show View" forState:UIControlStateNormal]; button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0); [self.view addSubview:button]; } } - (void)sendToController { NSLog(@"ok"); SpriteViewController *viewController = [SpriteViewController alloc]; [viewController openTweetSheet]; } 

我卡住的地方是试图让showTweetButton方法工作。 我的SpriteViewController.m看起来像这样:

 - (void)openTweetSheet { SLComposeViewController *tweetSheet = [SLComposeViewController composeViewControllerForServiceType: SLServiceTypeTwitter]; // Sets the completion handler. Note that we don't know which thread the // block will be called on, so we need to ensure that any required UI // updates occur on the main queue tweetSheet.completionHandler = ^(SLComposeViewControllerResult result) { switch(result) { // This means the user cancelled without sending the Tweet case SLComposeViewControllerResultCancelled: break; // This means the user hit 'Send' case SLComposeViewControllerResultDone: break; } }; // Set the initial body of the Tweet [tweetSheet setInitialText:@"just setting up my twttr"]; // Adds an image to the Tweet. For demo purposes, assume we have an // image named 'larry.png' that we wish to attach if (![tweetSheet addImage:[UIImage imageNamed:@"larry.png"]]) { NSLog(@"Unable to add the image!"); } // Add an URL to the Tweet. You can add multiple URLs. if (![tweetSheet addURL:[NSURL URLWithString:@"http://twitter.com/"]]){ NSLog(@"Unable to add the URL!"); } // Presents the Tweet Sheet to the user [self presentViewController:tweetSheet animated:NO completion:^{ NSLog(@"Tweet sheet has been presented."); }]; } 

我总是在日志中得到这样的东西:

– [UIView presentScene:]:无法识别的select器发送到实例0x13e63d00 2013-10-17 18:40:01.611修复[33409:a0b] *由于未捕获的exception'NSInvalidArgumentException',原因:' – [UIView presentScene:]:无法识别的select器发送到实例0x13e63d00'

您正在创build一个新的视图控制器,但从来没有提出:

 SpriteViewController *viewController = [SpriteViewController alloc]; 

我假设SpriteViewController是呈现你的SpriteMyScene ,你想把控制权交给展示的SpriteViewController

您需要在SpriteMyScene子类中保留对SpriteViewController的引用,然后在调用openTweetSheet时访问该引用。

在SpriteMyScene.h中

 @class SpriteViewController; @interface SpriteMyScene : SKScene @property (nonatomic, weak) SpriteViewController *spriteViewController; @end 

在SpriteViewController.m中

 // somewhere you initialize your SpriteMyScene object, I'm going to call it myScene myScene.spriteViewController = self; 

在SpriteMyScene.m中

 #import "SpriteViewController.h" - (void)sendToController { NSLog(@"ok"); // use the already-created spriteViewController [_spriteViewController openTweetSheet]; } 

您可以使用

 UIViewController *vc = self.view.window.rootViewController; 

这段代码会给你访问你的根视图控制器,所以你可以做任何事情你的视图控制器就像正常。

但是,你需要添加一个button? 在这种情况下,使用一个精灵并添加一个事件对你来说更好。 只要打电话:

 UIViewController *vc = self.view.window.rootViewController; [vc openTweetSheet]; 

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; NSArray *nodes = [self nodesAtPoint:[touch locationInNode:self]]; for (SKNode *node in nodes) { if ([node.name isEqualToString:@"OpenTweet"]) { UIViewController *vc = self.view.window.rootViewController; [vc openTweetSheet]; } } } 

如果要从场景中打开另一个UIViewController,则必须首先在主视图控制器中创build一个委托,该委托最初创build此场景,以便您的场景可以通知​​其ViewController打开tweet动作。 您将需要以下步骤:

  1. 在主视图控制器(我们的场景的视图控制器)中定义一个委托,以处理开启的鸣叫操作。
  2. 在主视图控制器中实现委托方法
  3. 在你的场景中添加一个委托属性,这样它可以保持ViewController委托方法实现的句柄。 在创build场景时,将此代理设置为主View Controller
  4. 检测场景中的事件以调用主ViewController的委托方法
  5. 在委托方法实现中,将控件传递给TweetSheetViewController

这是一个例子:

 @protocol ViewControllerDelegate <NSObject> -(void) openTweetSheet; @end 

扩展此ViewController以在其.h文件中支持此协议

 @interface ViewController : UIViewController<ViewControllerDelegate> @end 

然后在.m文件中实现协议中的方法

 -(void) openTweetSheet{ TweetSheetViewController *ctrl = [[TweetSheetViewController alloc] initWithNibName:@"TweetSheetViewController" bundle:nil]; [self presentViewController:ctrl animated:YES completion:nil]; } 

在你的场景头类中,添加一个委托属性

 @interface MyScene : SKScene { } @property (nonatomic, weak) id <ViewControllerDelegate> delegate; @end 

在ViewController中,在呈现场景之前,在viewDidLoad方法中设置它的委托:

 // Create and configure the scene. MyScene * scene = [MyScene sceneWithSize:skView.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; [scene setDelegate:self]; // Present the scene. [skView presentScene:scene]; 

现在,您的场景可以将消息传递回其ViewController,并且ViewController可以打开另一个ViewController。 在你的场景类中,确定触发TweetSheetViewController开放的动作

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* Called when a touch begins */ for (UITouch *touch in touches) { CGPoint location = [touch locationInNode:self]; SKAction *fadeOut = [SKAction fadeOutWithDuration:0.5]; SKAction *fadeIn = [SKAction fadeInWithDuration:1.0]; SKAction *sequence = [SKAction sequence:@[fadeOut,fadeIn]]; SKNode *node = [self nodeAtPoint:location]; if ([[node name] isEqual: @"openTweet"]) { NSLog(@"help"); [node runAction:sequence]; [delegate openTweetSheet]; } } 

希望有所帮助。

在您希望发生的场景中编写SlComposeViewController方法。 例如:

 @interface GameOverScene: SKScene ...initwithsize bla bla bla ... 

添加这些方法:

 -(void)OpenTweetShet{ if ([SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter]) { _composeTwitter = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter]; [_composeTwitter setInitialText:@"TWEET"]; 

然后打电话:

 self.view.window.rootViewController **to present the SLComposeViewController** [self.view.window.rootViewController presentViewController:_composeTwitter animated:YES completion:nil]; } [_composeTwitter setCompletionHandler:^(SLComposeViewControllerResult result){ NSString *output =[[NSString alloc]init]; switch (result) { case SLComposeViewControllerResultCancelled: output = @"Post cancelled"; break; case SLComposeViewControllerResultDone: output = @"Post Succesfull"; break; default: break; } 

这是发送/取消后显示UIAlert的选项:

 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Twitter" message:output delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; }]; } @end 

这对我工作:self.view.window.rootViewController

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; NSArray *nodes = [self nodesAtPoint:[touch locationInNode:self]]; for (SKNode *node in nodes) { if ([node.name isEqualToString:@"OpenTweet"]) { UIViewController *vc = self.view.window.rootViewController; [self.view.window.rootViewController openTweetSheet]; } } }