如何从Sprite Kit场景引用当前的Viewcontroller

stv*_*tvn 9 reference viewcontroller ios sprite-kit skscene

我很难找到这个问题的答案,我认为这并不难.

如何从SKScene引用在viewcontroller上定义的方法和属性?

并在此基础上:如何从另一个SKScene中加载的SKScene引用ViewController?

ton*_*har 11

比我的"后向引用"答案更好的选择是使用协议来显式定义SKScene子类期望UIViewController子类实现的方法.以下是您需要完成的步骤.

1)定义UIViewController需要采用并符合的协议(合同):

protocol GameManager{
    func loadHomeScene()
    func loadGameScene(level:Int)
    func loadHighScoreScene()
}
Run Code Online (Sandbox Code Playgroud)

2)UIViewController子类现在采用协议:

class GameViewController: UIViewController,GameManager{

3)GameScene得到一个参考的ivar UIViewController:

var gameManager:GameManager?

4)当GameManager需要调用时UIViewController,它会这样:

gameManager.loadHighScoreScene()

我们现在有一个明确定义的合同GameManager.在这个项目上工作的任何其他开发人员(以及当前开发人员未来的自己)现在知道GameManager应该实现哪些方法.这意味着我们可以轻松地将此代码移植到不同的项目(因此是不同的UIViewController),只要这个新的UIViewController采用GameManager协议,它仍然可以工作.

类似地,如果我们决定将场景导航代码移出视图控制器,而是将其放置在单例类中,则此单例类只需要采用该GameManager协议.

使用哪种方法?

这个帖子提供了解决问题的4种方法,我亲自使用了所有4.这是我对它们的看法:

1)硬编码UIViewController对子类的调用:

(self.view!.window!.rootViewController as! GameViewController).loadGameScene(1)

优势:1行代码!

缺点:2类的非常紧密的耦合,没有明确的合同.

2)使用指针返回UIViewController:

优点:所需代码非常少,无需协议.

缺点:2类紧耦合.没有明确的合同.

3)使用NSNotificationCenter:

优势:松散耦合的课程.

缺点:设置广播,接收器和回调方法需要更多代码.更难以跟踪和调试代码.没有明确的合同.通知的"一对多"功能很不错,但对我们没有帮助.

4)创建协议:

优点:明确的合同.MVC的众神会很高兴.

缺点:要编写更多代码(但比通知要少得多).


And*_*eev 9

您应该避免引用UIViewControllerSKScene,因为它打破了MVC模式.

作为替代方式,您可以使用NSNotificationCenter通知UIViewController高分:

ViewController:

- (void)awakeFromNib {
    [[NSNotificationCenter defaultCenter] 
        addObserver:self
        selector:@selector(reportScore:)
        name:@"ReportScore"
        object:nil];
}


-(void)reportScore:(NSNotification *) notification {
    NSDictionary *userInfo = [notification userInfo];
    NSNumber *scores = (NSNumber *)[userInfo objectForKey:@"scores"];
    // do your stuff with GameCenter....
}


- (void) dealloc
{
    // If you don't remove yourself as an observer, the Notification Center
    // will continue to try and send notification objects to the deallocated
    // object.
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
Run Code Online (Sandbox Code Playgroud)

SKScene:

- (void)gameOver {
    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:
         [NSNumber numberWithInt:self.scores forKey:@"scores"];
    [[NSNotificationCenter defaultCenter]
         postNotificationName:@"ReportScore" object:self userInfo:userInfo];
}
Run Code Online (Sandbox Code Playgroud)


小智 5

在理论上你不应该这样做,但在实践中......

self.view.window.rootViewController
Run Code Online (Sandbox Code Playgroud)