8

ユーザーがマップをズームまたはスクロールすると、MKMapView に従って UI を継続的に更新したいと思います。(スクロールが終了した後だけでなく、正常に動作します。)

デリゲート メソッド mapView:regionWillChangeAnimated: を試してみました。ドキュメントによると、「現在表示されているマップ領域が変更されるたびに呼び出されます。スクロール中に、このメソッドはマップ位置の更新を報告するために何度も呼び出される可能性があります。」 https://developer.apple.com/documentation/mapkit/mkmapviewdelegate

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    [self updateUIAcordingToMapViewRegionChange];
}

残念ながら、ドキュメントが真実を語っていないように見えるため、これは機能しません。このメソッドは、リージョン変更の最初に一度だけ呼び出されます。スクロール中、指が下がって動き回っている間、メソッドが再度呼び出されることはありません。

私が見つけたこの問題に関する唯一の投稿は、macrumors メンバー namanhams によるものでした: http://forums.macrumors.com/showthread.php?t=1225172 しかし、誰もアイデアを思いつきませんでした...

回避策として、regionWillChange でタイマーを設定しようとしました (そして、regionDidChange でそれを無効にしました):

- (void)handleRegionChange:(NSTimer*)timer
{
   [self updateUIAcordingToMapViewRegionChange];
} 

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    self.mapRegionIsChangingTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
                                                    target:self
                                                  selector:@selector(handleRegionChange:)
                                                  userInfo:nil
                                                   repeats:YES];
}

しかし、それもうまくいきません。タイマーからのすべてのメソッド呼び出しは、スクロールが終了した直後に一斉に実行されます。mapView のスクロールがメイン スレッドか何かをブロックしているようです…</p>

また、stackoverflow に関するこの投稿も読みましたが、残念ながら完全には理解できませんでした: Monitor MKMapView redraw events だから、私の問題の解決策が実際にその SO スレッドにある場合は、そのように教えてください。その詳細を掘り下げようとします。

私はまだ、正しいデリゲート メソッドを見つけるにはあまりにも愚かであるか、あまりにも盲目であることを願っています。また、MKMapView 領域の追跡に対処するためのヒント、回避策、およびベスト プラクティスを本当に感謝しています。

4

1 に答える 1

9

これは機能します:

@interface MapViewController () {
    NSTimer *_updateUITimer;
}

@end

@implementation MapViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    _updateUITimer = [NSTimer timerWithTimeInterval:0.1 
                                             target:self 
                                           selector:@selector(updateUI) 
                                           userInfo:nil 
                                            repeats:YES];

    [[NSRunLoop mainRunLoop] addTimer:_updateUITimer forMode:NSRunLoopCommonModes];

}

- (void)dealloc
{
    [_updateUITimer invalidate];
}

- (void)updateUI
{
    // Update UI
}

@end

もう1つの方法は、mapView:regionWillChangeAnimatedでタイマーを作成し、mapView:regionDidChangeAnimatedでタイマーを無効にすることです。

于 2012-10-24T09:08:53.633 に答える