我目前一直在使用委托和SKView自定义类来监控我的OS X SpriteKit游戏中的按键操作。我需要为我的键盘监控类使用多个委托,我知道这是不可能的,但是可以通过使用观察者来实现。如何实现这一目标?这是我使用委托模式的代码:
CustomSKView.h
#import <SpriteKit/SpriteKit.h>
@protocol KeyPressedDelegate;
@interface CustomSKView : SKView
@property (weak) id <KeyPressedDelegate> delegate;
@end
@protocol KeyPressedDelegate
- (void) upArrowPressed;
- (void) downArrowPressed;
@end
CustomSKView.m
#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 {
// Add code to handle a key down event here
if (self.delegate) {
switch (theEvent.keyCode) {
case 126: {
NSLog(@"delegate = %@", [self delegate]);
[self.delegate upArrowPressed];
break;
}
case 125:
[self.delegate downArrowPressed];
break;
default:
break;
}
}
}
@end
GameScene.h
#import <SpriteKit/SpriteKit.h>
#import "CustomSKView.h"
@interface GameScene : SKScene <KeyPressedDelegate>
@end
GameScene.m
#import "GameScene.h"
@implementation GameScene
-(void)didMoveToView:(SKView *)view {
((CustomSKView *)view).delegate = self;
}
- (void) upArrowPressed {
NSLog(@"Up Arrow Pressed");
}
- (void) downArrowPressed {
NSLog(@"Down Arrow Pressed");
}
@end
答案 0 :(得分:2)
您正在寻找NSNotificationCenter
。要将对象添加为观察者,请使用以下命令:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyPressed:)
name:@"KeyPressedNotificationKey"
object:nil];
这会导致该对象观察名称为@"KeyPressedNotificationKey"
的通知。要发布具有该名称的通知并附加已按下的键的keyCode,请调用:
[[NSNotificationCenter defaultCenter] postNotificationName:@"KeyPressedNotificationKey"
object:nil
userInfo:@{@"keyCode" : @(event.keyCode)];
发布通知时,任何观察者都会调用与观察者关联的方法。您可以从发布通知时附加的userInfo
字典中获取keyCode。在这种情况下,将使用具有此签名的方法调用:
- (void)keyPressed:(NSNotification *)notification
{
NSNumber *keyCodeObject = notification.userInfo[@"keyCode"];
NSInteger keyCode = keyCodeObject.integerValue;
// Do your thing
}
这有一个问题。一旦完成观察,您需要以观察者的身份移除对象。如果在不删除观察者的情况下释放对象,然后发布通知,它仍然会尝试在不存在的对象上调用该方法并崩溃。使用以下代码以观察者的身份删除对象:
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"NotificationNameKey"
object:nil];