简短版:
我遇到了一个问题,即在一个对象的不同实例上调用了一个方法,而不是 NSNotificationCenter 将通知推送到(尽管只创建了一个实例)。
长版:
我有一个由 OpenGL 更新/绘制循环操作的“拼图”对象实例。
我创建了一个 Control 单例来管理不同的触摸事件,如下所示:
@implementation Controls
static Controls *SharedGameControls = nil;
-(id)init {
self = [super init];
return self;
}
+ (Controls*)SharedGameControls{
if (SharedGameControls == nil){
SharedGameControls = [[super allocWithZone:NULL] init];
}
return SharedGameControls;
}
+ (id)allocWithZone:(NSZone *)zone
{
return self.SharedGameControls;
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
-(void)oneFingerSwipeDelegator:(UISwipeGestureRecognizer *)swipe{
switch (GState.currentMode)
{
case PuzzleLayer: {
CGPoint Origin = [swipe locationInView: _view];
//I believe this line should call oneFingerSwipe on the object instance
//provided to the singleton
[_oneFingerSwipeDelegate oneFingerSwipe:Origin Direction:swipe.direction];
break;
}
default:{
break;
}
}
}
-(void)setDefaultState{
GState = [GameState SharedGameState];
UISwipeGestureRecognizer *oneFingerSwipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(oneFingerSwipeDelegator:)];
[oneFingerSwipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
[_view addGestureRecognizer:oneFingerSwipeUp];
UISwipeGestureRecognizer *oneFingerSwipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(oneFingerSwipeDelegator:)];
[oneFingerSwipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
[_view addGestureRecognizer:oneFingerSwipeDown];
UISwipeGestureRecognizer *oneFingerSwipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(oneFingerSwipeDelegator:)];
[oneFingerSwipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[_view addGestureRecognizer:oneFingerSwipeLeft];
UISwipeGestureRecognizer *oneFingerSwipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(oneFingerSwipeDelegator:)];
[oneFingerSwipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[_view addGestureRecognizer:oneFingerSwipeRight];
UITapGestureRecognizer * single = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapDelegator:)];
single.numberOfTapsRequired = 1;
[_view addGestureRecognizer:single];
}
-(void)singleTapDelegator:(UITapGestureRecognizer *)tap{
CGPoint origin = [tap locationInView: _view];
NSValue *Origin = [NSValue valueWithCGPoint:origin];
switch (GState.currentMode)
{
case PuzzleLayer: {
[[NSNotificationCenter defaultCenter] postNotificationName:@"puzzleTap" object:nil userInfo:[NSDictionary dictionaryWithObject:Origin forKey:@"Origin"]];
break;
}
default:{
break;
}
}
}
@end
'_oneFingerSwipeDelegate' 在 .h 文件中定义为
@property (nonatomic, assign) id oneFingerSwipeDelegate;
然后在 Puzzle 类中,事件是这样处理的:
@implementation Puzzle
-(id)init{
self =[super init];
if (self){
GControls = [Controls SharedGameControls];
//I believe, possibly wrongly, that the line below will set this object instance
//to be the object oneFingerSwipe is called on
GControls.oneFingerSwipeDelegate = self;
GControls.twoFingerSwipeDelegate = self;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(singleTap:) name:@"puzzleTap" object:nil];
_Started = false;
//other code omitted
}
return self;
}
//implementation of the delegate in Controls.h
-(void)oneFingerSwipe:(CGPoint)touchPoint Direction:(UISwipeGestureRecognizerDirection)direction{
//do some stuff with objects inside puzzle
}
//observer for 'puzzleTap'
-(void)singleTap:(NSNotification*)note{
GLKVector3 Near,Far;
NSDictionary *dict = [note userInfo];
CGPoint origin = [[dict objectForKey:@"Origin"] CGPointValue ];
//Do stuff with objects inside puzzle
}
//other code omitted
@end
所以我正在测试手势识别以确保一切正常,我注意到我的滑动没有被处理。
点击正确地将通知发送到 Puzzle 对象中的 singleTap 方法(该方法在 Puzzle 实例的子对象上设置一个“已选择”标志)。
滑动正确地调用了拼图对象上的 oneFingerSwipe 方法,但由于某种原因无法检测到哪个对象已被点击“选择”。
仔细观察后,我注意到当我进入 singleTap 时,我看到了一个拼图对象的地址,这与进入 Control 单例调用的 oneFingerSwipe 方法时显示的地址不同。
如此有效,出于某种原因,Control 单例正在对通知发送到的对象的孪生实例进行操作(或相反)。每个实例中的所有对象似乎都具有与相应双胞胎不同的内存地址。
因此,当调用 oneFingerSwipe 时,子对象上的“选定”标志尚未更新,因此不会调用滑动逻辑。
当我切换到使用通知进行滑动时,问题就消失了。
我真的不明白这里发生了什么。当我将拼图实例分配给 oneFingerSwipe 属性时,控制单例是否会创建拼图实例的副本?
我使用Objective C 只工作了大约6 个月,还有很多我不明白的地方。
感谢您通过那堵文字墙,感谢您抽出时间来看看。