簡體   English   中英

防止MKMapView改變選擇(干凈地)

[英]Preventing MKMapView changing selection (cleanly)

我有一個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;
}

請注意,我也關閉選擇,以便在我重寫的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];
    }


}

這條線評論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;

}

-(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;
}

這一切似乎沒有任何缺點和下行(就像我從其他解決方案中看到的閃爍一樣。它相對簡單,但感覺不對。

誰有更好的解決方案?

我不認為你需要使用地圖視圖的選擇跟蹤。 如果我正確地解釋了你想要的東西,你應該只用hitTest:withEvent: override和canShowCallout設置為NO來完成它。 setSelected:執行你的標注出現/消失動畫。 您還應該覆蓋setHighlighted:並調整自定義標注的顯示(如果可見)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM