简短版本:
我遇到了一个问题,即在一个对象的不同实例上调用方法而不是NSNotificationCenter正在向其发送通知(尽管只创建了一个实例)。
长版:
我有一个“Puzzle”对象实例,由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实例的子对象上设置'selected'标志)。
正确滑动调用拼图对象上的oneFingerSwipe方法,但由于某种原因无法检测到哪个对象已被“选中”。
仔细观察之后,我注意到当我进入singleTap时,我会看到拼图对象的地址,该地址与步入Control单例调用的oneFingerSwipe方法时显示的地址不同。
因此,有效地,Control单例操作在发送通知(或反向)的对象的双实例上。每个实例中的所有对象似乎都有不同的内存地址。
因此,当调用oneFingerSwipe时,未在子对象上更新“selected”标志,因此不会调用滑动逻辑。
当我切换到使用滑动通知时,问题就消失了。
我真的不明白这里发生了什么。当我将拼图实例分配给oneFingerSwipe属性时,Control单例是否创建了Puzzle实例的副本?
我只使用Objective C工作了大约6个月,并且有很多我不明白的事情。
感谢您浏览文字墙,感谢您抽出时间来观看。
答案 0 :(得分:0)
直接方法调用似乎发生在与NSNotificationCenter不同的对象上的原因是推送通知是因为它实际上是一个不同的对象。我已经在一个循环中实例化了许多不同的拼图对象,而每个拼图对象又将自己设置为oneFingerSwipe的目标。当我走过时,碰巧看着两个非常相似但又不同的物体,错误地得出结论,一个是另一个的副本。非常感谢评论者花时间看这个冗长的问题并指出我正确的方向。现在我已经转而只使用NSNotifications了,但我会更多地阅读使用代表,看看是否更符合我的需求。