¿Cómo presento un UIViewController de SKScene?

Estoy ingresando a iOS a través de Sprite Kit, que reconozco que no es prudente.

Mi objective es mostrar un botón “Compartir” en Game Over. Tocando el botón compartir debe presentar un SLComposeViewController (Twitter Share). El contenido de la escena no debería cambiar.

La lógica del juego que dicta “Game Over” vive en SpriteMyScene.m, una subclase de SKScene.

Puedo mostrar un botón Compartir en el juego de esta manera:

-(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]; } 

Donde me quedo estan tratando de hacer que el método showTweetButton funcione. Mi SpriteViewController.m se ve así:

 - (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."); }]; } 

Siempre obtengo algo como esto en los registros:

– [UIView presentScene:]: selector no reconocido enviado a la instancia 0x13e63d00 2013-10-17 18: 40: 01.611 Fix [33409: a0b] * Aplicación de finalización debido a una excepción no detectada ‘NSInvalidArgumentException’, razón: ‘- [UIView presentScene:]: selector no reconocido enviado a la instancia 0x13e63d00 ‘

Está creando un nuevo controlador de vista pero nunca lo presenta:

 SpriteViewController *viewController = [SpriteViewController alloc]; 

Supongo que SpriteViewController es lo que presenta su SpriteMyScene , y desea devolver el control al SpriteViewController presenta.

SpriteViewController mantener una referencia a SpriteViewController en su subclase SpriteMyScene y luego acceder a esa referencia cuando llame a openTweetSheet .

en SpriteMyScene.h

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

en SpriteViewController.m

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

en SpriteMyScene.m

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

Puedes usar

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

Este código le dará acceso a su controlador de vista raíz para que pueda hacer cualquier cosa que haga su controlador de vista como lo hace normalmente.

Sin embargo, ¿necesitas agregar un botón? Usar un sprite y agregarle un evento es mejor para ti en este caso. Solo llama:

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

Y

 -(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]; } } } 

Si desea abrir otro UIViewController desde el interior de su escena, primero debe crear un delegado en el Controlador de vista primario que creó originalmente esta escena para que su escena pueda notificar a su ViewController de una acción de tweet abierta. Necesitará los siguientes pasos:

  1. Defina un delegado en el controlador de vista primario: el controlador de vista de nuestra escena, para manejar la acción de tweet abierto.
  2. Implementar el método de delegado en el controlador de vista primario
  3. Agregue una propiedad de delegado en su escena para que pueda mantener un control sobre la implementación del método delegado de ViewController. Establezca este delegado como el controlador de vista principal durante la creación de la escena
  4. Detecta un evento en la escena para llamar al método de delegado del ViewController primario
  5. En la implementación del método de delegado pase el control al TweetSheetViewController

Aquí está el ejemplo:

 @protocol ViewControllerDelegate  -(void) openTweetSheet; @end 

Extienda este ViewController para admitir este protocolo en su archivo .h

 @interface ViewController : UIViewController @end 

Luego, en el archivo .m, implemente el método del protocolo

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

En la clase de encabezado de escena, agregue una propiedad de delegado

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

En ViewController, antes de presentar la escena, establezca su delegado en el método 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]; 

Ahora su escena puede pasar el mensaje a su ViewController y ViewController puede abrir otro ViewController. En tu clase de escena, determina la acción que activará la apertura de 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]; } } 

Espero que ayude.

Escriba el Método SlComposeViewController en la escena que desea que tenga lugar. Por ejemplo:

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

Agregue estos métodos:

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

Luego llame:

 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; } 

Aquí está la opción para presentar UIAlert después de la publicación de envío / cancelación:

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

Esto funcionó para mí: 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]; } } }