3

MKMapViewでメモリリークの問題が継続的に発生しているため(Appleに報告されましたが、応答がありません)、回避策として、新しいマップを再割り当てする代わりに、1つのMKMapViewを割り当ててそのマップを再利用しようとしました。これで発生している問題は、MKMapViewを元のビューにリセットすることがまだできないことです。私はアメリカで働いているので、最初は次のような見方をしていると思います。

アメリカの地図
(出典:cprince.com

このコードで:

static MKMapView *map = nil;

- (void) showUserLocation {    
    [map setShowsUserLocation:YES];

    CLLocationCoordinate2D coord;

    coord.latitude = 39.0; // changed from original coords
    coord.longitude = -105.0;

    MKCoordinateRegion r = MKCoordinateRegionMakeWithDistance(coord, 1000, 1000);

    [map setRegion:r animated:YES];
}

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (! map) {
        CGRect r = CGRectMake(20, 50, 196, 75);
        map = [[MKMapView alloc] initWithFrame:r];

        defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    } else {
        [map setRegion:defaultRegion animated:YES];
    }

    [self.view addSubview:map];
}

- (IBAction)annotateMap:(id)sender {
    [self showUserLocation];
}

annotateMapを呼び出すボタンをクリックすると、次のマップが表示されます(まだ驚きはありません)。

私の家の地図
(出典:cprince.com

次に、このビューから(ナビゲーションコントローラーを使用して)移動してからビューに再度入ると(viewWillAppearが再度呼び出されますが、今回は以前に割り当てられたMKMapViewを再利用します)、次のマップビューが表示されます。

海の地図
(出典:cprince.com

そしてもちろん、viewWillAppearのこの部分のために、元のデフォルト領域を取得する必要があります。

        defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    } else {
        [map setRegion:defaultRegion animated:YES];
    }

addSubviewの後または前にsetRegionを実行するかどうかは関係ありません。つまり、以下の変更は問題を修正しません。

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    BOOL firstTime = NO;
    if (! map) {
        firstTime = YES;
        CGRect r = CGRectMake(20, 50, 196, 75);
        map = [[MKMapView alloc] initWithFrame:r];

        defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    }

    [self.view addSubview:map];
    if (! firstTime) {
        [map setRegion:defaultRegion animated:YES];
    }
}

MKMapRectWorldを使用しても効果はありません。

defaultRegion = MKCoordinateRegionForMapRect(MKMapRectWorld);

この問題は、MKMapViewのある種の競合状態によるものでもありません。ボタンのハンドラーを変更した場合:

- (IBAction)annotateMap:(id)sender {
    defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    [self showUserLocation];
}

ボタンをクリックする前に、マップがUSAビューに確定するまで待ってください。問題は、同じです。

iOS6.1.2とXCode4.6を使用しています。

(完全なXCodeプロジェクトはhttp://www.cprince.com/stackoverflow/Map.zipで入手できます)。

考え?

最初の変更

defaultRegionをインスタンス変数ではなく静的にしたのですが、これによって状況が大きく変わることはありません。(以下のデフォルト領域の緯度/経度を報告しました)。マップの結果は次のとおりです。

海の地図
(出典:cprince.com

わかりやすくするために、現在のコードは次のとおりです。

static MKMapView *map = nil;
static MKCoordinateRegion defaultRegion;

- (void) showUserLocation {    
    [map setShowsUserLocation:YES];

    CLLocationCoordinate2D coord;
    coord.latitude = 39.0; // changed from original
    coord.longitude = -105.0;

    MKCoordinateRegion r = MKCoordinateRegionMakeWithDistance(coord, 1000, 1000);

    [map setRegion:r animated:YES];
}

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    BOOL firstTime = NO;
    if (! map) {
        firstTime = YES;
        CGRect r = CGRectMake(20, 50, 196, 75);
        map = [[MKMapView alloc] initWithFrame:r];

        defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));

        NSLog(@"defaultRegion: center: lat: %f, long: %f; span: %f dlat: dlong: %f", defaultRegion.center.latitude, defaultRegion.center.longitude, defaultRegion.span.latitudeDelta, defaultRegion.span.longitudeDelta);
        //defaultRegion = MKCoordinateRegionForMapRect(MKMapRectWorld);
    }

    [self.view addSubview:map];
    if (! firstTime) {
        NSLog(@"defaultRegion: center: lat: %f, long: %f; span: %f dlat: dlong: %f", defaultRegion.center.latitude, defaultRegion.center.longitude, defaultRegion.span.latitudeDelta, defaultRegion.span.longitudeDelta);
        [map setRegion:defaultRegion animated:YES];
    }
}

- (IBAction)annotateMap:(id)sender {
    //defaultRegion = MKCoordinateRegionMake(map.centerCoordinate, MKCoordinateSpanMake(180, 360));
    [self showUserLocation];
}
4

1 に答える 1

3

ビューコントローラdelegateMKMapViewとに実装すると、最初にマップビューを作成したときに、がに設定されてregionDidChangeAnimatedいることがわかりますが、その後はに設定されます(少なくとも米国のユーザーの場合)。どうやら、マップビューを作成した直後に、および/またはに依存することはできません。をリセットする機会を与える必要がありますが、これは明らかに非同期で発生します。centerCoordinate30, -4037.178181, -96.054581regioncenterCoordinateregion

を最初に設定したdefaultRegion後に保存する場合は、のプロパティを設定してから、以下を実装します。MKMapViewdelegateMKMapView

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    static BOOL firstTime = YES;
    if (firstTime)
    {
        defaultRegion = mapView.region;
        firstTime = NO;
    }
}

に注意してviewWillDisappearください。マップを作成したので、マップstaticを確認してください(古いView Controllerが表示されなくなるため)。ビューコントローラの新しいインスタンスを引き続き使用する場合は、詳細ビューコントローラの新しいインスタンスにマップビューを再度追加するときに、もう一度設定します。nildelegateMKMapViewDelegatedelegate


古い答え:

を設定するdefaultRegionと、それはインスタンス変数になります。したがって、ビューを閉じると、それは失われます。マップに戻ると(つまりfirstTimeNO)、defaultRegionは初期化されないため、0,0であり、したがって大西洋の真ん中にあります。

明らかに保存していませんdefaultRegion(通常、マスタービューコントローラーに戻すプロトコルがあります)。これにより、マスタービューでアイテムを再度選択したときに、アプリが何をすべきかを知ることが困難になります。

于 2013-03-22T00:20:47.967 に答える