Rog*_*Rog 5 objective-c mkmapview uigesturerecognizer ios uievent
我有一个自定义子类MKPinAnnotationView,显示自定义调用.我想处理该注释中的触摸事件.
我有一个有效的解决方案(下图),但感觉不对.我有一个经验法则,每当我使用时,performSelector: .. withDelay:我都在与系统作战而不是使用它.
有没有人为MKMapView和注释选择处理的积极事件处理有一个良好,干净的解决方法?
我目前的解决方案
(我的注释选择类中的所有代码)
我进行自己的热门测试(没有这个我的手势识别器不会触发,因为Map View会消耗这些事件:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event; {
// To enable our gesture recogniser to fire. we have to hit test and return the correct view for events inside the callout.
UIView* hitView = nil;
if (self.selected) {
// check if we tpped inside the custom view
if (CGRectContainsPoint(self.customView.frame, point))
hitView = self.customView;
}
if(hitView) {
// If we are performing a gesture recogniser (and hence want to consume the action)
// we need to turn off selections for the annotation temporarily
// the are re-enabled in the gesture recogniser.
self.selectionEnabled = NO;
// *1* The re-enable selection a moment later
[self performSelector:@selector(enableAnnotationSelection) withObject:nil afterDelay:kAnnotationSelectionDelay];
} else {
// We didn't hit test so pass up the chain.
hitView = [super hitTest:point withEvent:event];
}
return hitView;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我也关闭了选择,以便在我被覆盖时setSelected我可以忽略取消选择.
- (void)setSelected:(BOOL)selected animated:(BOOL)animated; {
// If we have hit tested positive for one of our views with a gesture recogniser, temporarily
// disable selections through _selectionEnabled
if(!_selectionEnabled){
// Note that from here one, we are out of sync with the enclosing map view
// we're just displaying out callout even though it thinks we've been deselected
return;
}
if(selected) {
// deleted code to set up view here
[self addSubview:_customView];
_mainTapGestureRecogniser = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(calloutTapped:)];
[_customView addGestureRecognizer: _mainTapGestureRecogniser];
} else {
self.selected = NO;
[_customView removeFromSuperview];
}
}
Run Code Online (Sandbox Code Playgroud)
这条线评论1,我不喜欢,但它在theta延迟火灾结束时也非常毛茸茸.我必须走回superview链才能到达mapView,以便我可以说服选择仍然存在.
// Locate the mapview so that we can ensure it has the correct annotation selection state after we have ignored selections.
- (void)enableAnnotationSelection {
// This reenables the seelction state and resets the parent map view's idea of the
// correct selection i.e. us.
MKMapView* map = [self findMapView];
[map selectAnnotation:self.annotation animated:NO];
_selectionEnabled = YES;
}
Run Code Online (Sandbox Code Playgroud)
同
-(MKMapView*)findMapView; {
UIView* view = [self superview];
while(!_mapView) {
if([view isKindOfClass:[MKMapView class]]) {
_mapView = (MKMapView*)view;
} else if ([view isKindOfClass:[UIWindow class]]){
return nil;
} else{
view = [view superview];
if(!view)
return nil;
}
}
return _mapView;
}
Run Code Online (Sandbox Code Playgroud)
这一切似乎没有任何缺点和下行(就像我从其他解决方案中看到的闪烁一样.它相对简单,但感觉不对.
谁有更好的解决方案?
我认为您不需要胡闹地图视图的选择跟踪。如果我正确地解释了您想要的内容,您应该能够仅通过hitTest:withEvent:覆盖并canShowCallout设置为 来完成它NO。相应地执行setSelected:标注出现/消失动画。您还应该覆盖setHighlighted:并调整自定义标注的显示(如果可见)。