我如何从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动作。 您将需要以下步骤:
- 在主视图控制器(我们的场景的视图控制器)中定义一个委托,以处理开启的鸣叫操作。
- 在主视图控制器中实现委托方法
- 在你的场景中添加一个委托属性,这样它可以保持ViewController委托方法实现的句柄。 在创build场景时,将此代理设置为主View Controller
- 检测场景中的事件以调用主ViewController的委托方法
- 在委托方法实现中,将控件传递给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]; } } }