首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSNotificationCenter与SpriteKit

NSNotificationCenter与SpriteKit
EN

Stack Overflow用户
提问于 2015-08-15 09:16:36
回答 2查看 262关注 0票数 2

我使用NSNotificationCenter通知何时按下键盘上的键。当在场景之间移动时,如果在按下导致场景转换的键后,另一个键被按得太快,则应用程序会崩溃。我不确定是上一个场景不再接收通知,还是下一个场景的通知观察者没有被设置。我能做些什么来阻止这一切的发生?下面是两个不同场景的代码和处理通知的自定义视图。本质上,我在CustomSKView中发布了一个键按压通知,然后在这里没有列出的一个名为keyPressed:的方法中处理相应场景中的按键。

LevelSelectScene.m

代码语言:javascript
复制
@implementation LevelSelectScene

-(void)didMoveToView:(SKView *)view {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyPressed:) name:@"KeyPressedNotificationKey" object:nil];

    //perform scene setup here
    ...
}

-(void)willMoveFromView:(SKView *)view {
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:@"KeyPressedNotificationKey"
                                              object:nil];

    //perform additional cleanup before moving to next scene
    ...

}

Menu.m

代码语言:javascript
复制
-(void) didMoveToView:(SKView *)view {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyPressed:) name:@"KeyPressedNotificationKey" object:nil];

    //perform menu setup here
    ...
}


-(void) willMoveFromView:(SKView *)view {
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:@"KeyPressedNotificationKey"
                                              object:nil];

    //perform additional cleanup before moving to next scene
    ...
}

CustomSKView.m

代码语言:javascript
复制
#import "CustomSKView.h"

@implementation CustomSKView:SKView {

}

- (id) initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    return self;
}

- (void) keyDown:(NSEvent *)theEvent {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"KeyPressedNotificationKey"
                                                        object:nil
                                                      userInfo:@{@"keyCode" : @(theEvent.keyCode)}];
}

@end

编辑:堆栈跟踪

代码语言:javascript
复制
2015-08-15 05:47:08.199 PianoKeyboardTest[21854:4643404] -[NSPathStore2 keyPressed:]: unrecognized selector sent to instance 0x10050d110
2015-08-15 05:47:08.199 PianoKeyboardTest[21854:4643404] -[NSPathStore2 keyPressed:]: unrecognized selector sent to instance 0x10050d110
2015-08-15 05:47:08.200 PianoKeyboardTest[21854:4643404] (
0   CoreFoundation                      0x00007fff8575803c __exceptionPreprocess + 172
1   libobjc.A.dylib                     0x00007fff9227376e objc_exception_throw + 43
2   CoreFoundation                      0x00007fff8575b0ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3   CoreFoundation                      0x00007fff856a0e24 ___forwarding___ + 1028
4   CoreFoundation                      0x00007fff856a0998 _CF_forwarding_prep_0 + 120
5   CoreFoundation                      0x00007fff8571445c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
6   CoreFoundation                      0x00007fff85604634 _CFXNotificationPost + 3140
7   Foundation                          0x00007fff83e8e9d1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
8   PianoKeyboardTest                   0x000000010001d50e -[CustomSKView keyDown:] + 270
9   AppKit                              0x00007fff8ba1c11b -[NSWindow _reallySendEvent:isDelayedEvent:] + 5452
10  AppKit                              0x00007fff8b3add76 -[NSWindow sendEvent:] + 470
11  AppKit                              0x00007fff8b3aa9b1 -[NSApplication sendEvent:] + 4199
12  AppKit                              0x00007fff8b2d3c68 -[NSApplication run] + 711
13  AppKit                              0x00007fff8b250354 NSApplicationMain + 1832
14  PianoKeyboardTest                   0x0000000100005322 main + 34
15  libdyld.dylib                       0x00007fff8f1ee5c9 start + 1
)

编辑:解决方案

下面是我对CustomSKView所做的更改。

代码语言:javascript
复制
#import "CustomSKView.h"

@implementation CustomSKView:SKView {
    // Add instance variables here

}

- (id) initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        // Allocate and initialize your instance variables here

    }
    return self;
}

- (void) keyDown:(NSEvent *)theEvent {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"KeyPressedNotificationKey"
                                                        object:nil
                                                      userInfo:@{@"keyCode" : @(theEvent.keyCode)}];
}

//overridden version of SKScene's presentScene: transition: method
-(void) presentScene:(SKScene *)scene transition:(SKTransition *)transition {
    [[NSNotificationCenter defaultCenter] removeObserver:self.scene
                                                    name:@"KeyPressedNotificationKey"
                                                  object:nil];
    [super presentScene:scene transition:transition];
}

@end
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-16 07:23:36

若要在游戏过渡到新场景时从当前SKScene中删除观察者,请重写自定义视图类中的presentScene方法,移除观察者,然后调用超类的presentScene

代码语言:javascript
复制
- (void) presentScene:(SKScene *)scene transition:(SKTransition *)transition {
    [[NSNotificationCenter defaultCenter] removeObserver:self.scene
                                                    name:@"KeyPressedNotificationKey"
                                                  object:nil];
    [super presentScene:scene transition:transition];
 }
票数 1
EN

Stack Overflow用户

发布于 2015-08-15 23:51:31

问题似乎在于时机问题。您需要在转换开始之前删除通知,但是SKView没有为此提供一个方便的挂钩。

一种可能的管理方法是子类SKView,提供添加和删除观察者的机制,并可能使用多个通知;一个用于击键,另一个用于转换开始/结束。当触发转换开始通知时,此子类将删除击键观察者。当转换完成后,可以通知它重新观察击键。然而,这听起来确实很复杂。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32023322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档