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的众神会很高兴.
缺点:要编写更多代码(但比通知要少得多).
您应该避免引用UIViewController从SKScene,因为它打破了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)