Как мне представить UIViewController из SKscene с социальной структурой?

Я делаю игру наподобие Flappy Bird. Как представить UIViewController из SKScene? Прежде всего, я говорю своим окружениям

  • Mac OS X 10.9
  • Xcode 5.0.2
  • Sprite Kit(framework), social.framework(framework) добавлены в мой проект

Моя цель - отобразить кнопку «Поделиться» после окончания игры. При нажатии на изображение кнопки «Поделиться» должен появиться SLComposeViewController (Twitter Share). Содержимое сцены не должно меняться.
Я хотел бы решить следующую проблему и изменить отображение с GameOverScene на tweetSheet(отображение), составленное с помощью social.framework.

Проблема

[self presentViewController:tweetSheet animated:YES completion:nil];
//Error:No visible @interface for 'GameOverScene' declares the selector "presentViewController":animated:completion:


Мои файлы кодирования находятся ниже (я извлек части важных кодов).

ViewController.h

import <UIKit/UIKit.h>
import <SpriteKit/SpriteKit.h>
import <iAd/iAd.h>

@interface ViewController : UIViewController<ADBannerViewDelegate><br>

@end

GameOverScene.h

#import <SpriteKit/SpriteKit.h> 

@class SpriteViewController;

@interface GameOverScene : SKScene {
}
@end

GameOverScene.m

#import "GameOverScene.h"
#import "NewGameScene.h"
#import "MainScene.h"
#import <Social/Social.h>
@implementation GameOverScene {
   //The twitter button 
    SKSpriteNode *_twitterbutton;
}
- (id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size]) {
        //Creating the twitterbutton with the twitterbutton image from Images.xcassets
        _twitterbutton = [SKSpriteNode spriteNodeWithImageNamed:@"twitterbutton"];
        [_twitterbutton setSize:CGSizeMake(50, 50)];
        [_twitterbutton setPosition:CGPointMake(self.size.width/2, self.size.height/5 + 50)];
        //Adding the twitter button
        [self addChild:_twitterbutton];
        //Again, this is important, otherwise we can't identify what button is pressed
        _twitterbutton.name = @"twitterbutton";
        [_twitterbutton setPosition:CGPointMake(self.size.width/2, self.size.height/5 + 50)]
    }
    return self;
}


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //Same as in NewGameScene menu
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:location];
    //Is the twitter button touched?
    if([node.name isEqualToString:@"twitterbutton"]){
        if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]){
            SLComposeViewController *tweetSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
            [tweetSheet setInitialText:@"TestTweet from the Game !!"];
            [self presentViewController:tweetSheet animated:YES completion:nil];
     **//Error:No visible @interface for 'GameOverScene' declares the selector "presentViewController":animated:completion:**
         } 
    }

ViewControlloer.m

#import "ViewController.h"
#import "NewGameScene.h"
@implementation ViewController
//Loads the view onto our main class
- (void)loadView
{
  self.view  = [[SKView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
}
//Executes when view finishes loading
- (void)viewWillLayoutSubviews
{
  [super viewDidLoad];

  //Set the resize mode to flexible width and height
  [self.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];

  //Create our view from our original view
  //Make sure to leave originalContentView in, otherwise the app will crash
  SKView *skView = (SKView *)self.originalContentView;

  //We create a new NewGameScene according to the current dimensions
  SKScene *scene = [NewGameScene sceneWithSize:skView.bounds.size];

  //Create a transition class with animation type fade and a duration of .4 seconds
  SKTransition *transition = [SKTransition fadeWithDuration:.4];

  //Present the menu view (NewGameScene) with our fade in transition
  [skView presentScene:scene transition:transition];
}

@end

person Yaemon    schedule 15.03.2014    source источник
comment
Здесь вставлено много кода, сомневаюсь, что кто-то будет это читать. Прочтите это руководство о том, как наилучшим образом представить свою проблему: stackoverflow.com/help/mcve Этот процесс также поможет вам лучше понять его.   -  person Henrik    schedule 15.03.2014
comment
Дубликат [stackoverflow.com/questions/19438719/ [1]: stackoverflow.com/questions/19438719/   -  person Theis Egeberg    schedule 15.03.2014
comment
››Henrik Спасибо за совет!! Я впервые задаю свой вопрос. Если ты злишься, мне очень жаль. Я воспользуюсь вашим полезным советом, большое спасибо, сэр. ››Theis Спасибо за совет. Однако я новичок в Xcode. Я знал статью и читал все больше и больше, но все же не мог понять... Итак, я задал этот вопрос. Что мне делать как вы думаете как прочитать статью??? stackoverflow.com/ вопросы/19438719/   -  person Yaemon    schedule 15.03.2014
comment
@tomojiro Не волнуйтесь, не злитесь, просто пытаюсь помочь начинающему автору улучшить вопрос, чтобы получить больше ответов. :)   -  person Henrik    schedule 15.03.2014


Ответы (1)


Вы не можете представить viewController из SKScene, поскольку на самом деле он отображается только в SKView. Вам нужен способ отправить сообщение в viewController, который, в свою очередь, представит viewController. Для этого вы можете использовать делегирование.

Добавьте следующее определение протокола в файл .h вашего SKScene:

@protocol sceneDelegate <NSObject>
-(void)showShareScreen;
@end

И объявите свойство делегата в интерфейсе:

@property (weak, nonatomic) id <sceneDelegate> delegate;

Затем в том месте, где вы хотите представить экран общего доступа, вместо строки:

[self presentViewController:tweetSheet animated:YES completion:nil];

Используйте эту строку:

[self.delegate showShareScreen];

Теперь в файле .h вашего viewController реализуйте протокол:

@interface ViewController : UIViewController <sceneDelegate>

И в вашем файле .m добавьте следующую строку перед представлением сцены:

scene.delegate = self;

Затем добавьте туда следующий метод:

-(void)presentShareScreen
{

    if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
    {
        SLComposeViewController *tweetSheet = [SLComposeViewController
        composeViewControllerForServiceType:SLServiceTypeTwitter];
        [tweetSheet setInitialText:@"TestTweet from the Game !!"];
        [self presentViewController:tweetSheet animated:YES completion:nil];

    }
}

Альтернативным методом может быть использование NSNotificationCenter.

Сохраните метод -presentShareScreen, как описано в предыдущем варианте.

Добавьте viewController в качестве слушателя уведомления в методе -viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(presentShareScreen) name:@"showShareScreen" object:nil];

Затем в сцене в том месте, где вы хотите показать этот viewController, используйте эту строку:

[[NSNotificationCenter defaultCenter] postNotificationName:@"showShareScreen" object:nil];

person ZeMoon    schedule 15.03.2014
comment
Я так рад видеть ваш ответ, спасибо. Но я не уверен, как использовать следующую строку scene.delegate = self; Где я должен использовать в файле .m? Когда я использовал его в файле ViewController.m, это не сработало. И он говорит, что свойство «делегат» не найдено для объекта типа SKScene - person Yaemon; 16.03.2014
comment
Вам нужно добавить протокол перед определением интерфейса вашего GameOverScene. - person ZeMoon; 16.03.2014
comment
Я так запутался... Я должен найти SKScene и добавить протокол в файл SKScene. Я добавил протокол в подкласс SKScene, например, @interface MainScene : SKScene ‹sceneDelegate› Сейчас я так запутался, но я сделаю все возможное :) - person Yaemon; 16.03.2014
comment
Ммм... Я заменил [self.delegate showShareScreen]; к моему методу Twitter GameOverScene.m. Но мой ViewController.m не делегирует метод (showShareScreen). Это сработало, но не делегирует, потому что когда я использую точку останова в методе showShareScreen, он не останавливается... Могу я узнать причину ??? Кстати, для использования scene.delegate = self; Я сделал экземпляр из экземпляра GameOverScene. У меня работает, наверное. - person Yaemon; 17.03.2014
comment
@tomojiro Я добавил более простой и альтернативный метод для этой проблемы. - person ZeMoon; 22.03.2014
comment
Большое спасибо за ваш совет. Я понял, что существует еще один экземпляр экземпляра GameOverScene, поэтому я не делегировал свойство. Я создал новый viewController. Более того, я делегировал viewController из GameOverScene.m. Но возникает другая проблема, здесь ?noredirect=1#comment34353639_22568353" title="предупреждение о попытке представить, чье представление не находится в иерархии окон"> stackoverflow.com/questions/22568353/ Сейчас я решаю эту проблему, в любом случае большое спасибо , сэр !! - person Yaemon; 22.03.2014
comment
@tomojiro Пожалуйста, примите этот ответ, если он решил вашу проблему. - person ZeMoon; 08.02.2016