1

我希望一旦单击“咖啡馆”之类的工具栏按钮,咖啡馆将显示在可见的地图区域中。数据是从 Google Places API 获取的。一切正常,除了单击按钮后不显示引脚。

这里肯定会出现延迟。然而,我在后台队列中进行提取并在等待时放置一个纺车,当抓取和解析完成时纺车会隐藏起来。所以我很确定在纺车消失的那一刻数据就在那里。但是在我滚动地图之前,这些图钉不会出现。

我认为滚动地图只会触发mapView:regionDidChangeAnimated:。但我无法弄清楚它与问题的关系。任何人都可以帮忙吗?

的源代码ViewController.m,几乎所有事情都发生在这里。

#import "ViewController.h"
#import "MapPoint.h"
#import "MBProgressHUD.h"

#define kGOOGLE_API_KEY @"AIzaSyCHqbAoY7WCL3l7x188ZM4ciiTixejzQ4Y"
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)



@interface ViewController () <CLLocationManagerDelegate, MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (strong, nonatomic) CLLocationManager *locationManager;
@property int currentDist;
@property CLLocationCoordinate2D currentCentre;
@end

@implementation ViewController
@synthesize mapView = _mapView;
@synthesize locationManager = _locationManager;
@synthesize currentDist = _currentDist;
@synthesize currentCentre = _currentCentre;

- (void)viewDidLoad{
    [super viewDidLoad];
}


- (void)viewDidUnload{
    [self setMapView:nil];
    [super viewDidUnload];
}

// set the map region after launching
-(void)viewWillAppear:(BOOL)animated
{
    //Instantiate a location object.
    self.locationManager = [[CLLocationManager alloc] init];

    //Make this controller the delegate for the location manager.
    self.locationManager.delegate = self;

    //Set some parameters for the location object.
    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

    // order: latitude(纬度), longitude(经度)
    CLLocationCoordinate2D center = self.locationManager.location.coordinate;

    // 单位是degree
    MKCoordinateSpan span = MKCoordinateSpanMake(0.03, 0.03);

    MKCoordinateRegion region = MKCoordinateRegionMake(center, span);

    [self.mapView setRegion:region animated:YES];

    // NSLog(@"currentCentre is (%f , %f)", self.currentCentre.latitude, self.currentCentre.longitude);
}

// Get place tpye from button title
// All buttons share this one method
- (IBAction)toolbarButtonPressed:(id)sender
{
    UIBarButtonItem *button = (UIBarButtonItem *)sender;
    NSString *buttonTitle = [button.title lowercaseString];

    //Use this title text to build the URL query and get the data from Google.
    [self queryGooglePlaces:buttonTitle];

}

// Parse response JSON data
-(void)parseData:(NSData *)responseData {

    NSError* error;
    NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
                                                         options:kNilOptions
                                                        error:&error];

    //The results from Google will be an array obtained from the NSDictionary object with the key "results".
    NSArray* places = [json objectForKey:@"results"];
    [self plotPositions:places];
    NSLog(@"Plot is done");
}

// Format query string
-(void) queryGooglePlaces: (NSString *) googleType {

    // query string
    NSString *url = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/place/search/json?location=%f,%f&radius=%@&types=%@&sensor=true&key=%@", self.currentCentre.latitude, self.currentCentre.longitude, [NSString stringWithFormat:@"%i", _currentDist], googleType, kGOOGLE_API_KEY];

    //string to URL 
    NSURL *googleRequestURL=[NSURL URLWithString:url];

    // Retrieve data from the query URL by GCD
    dispatch_async(kBgQueue, ^{
        NSData* data = [NSData dataWithContentsOfURL: googleRequestURL];
        [self parseData:data];
        [MBProgressHUD hideHUDForView:self.view animated:YES];
    });

    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.labelText = @"Please Wait..";
}

#pragma mark - Map View Delegate

// called many times when map scrolling or zooming
// Use this to get currentCentre and currentDist (radius)

-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    //Get the east and west points on the map so you can calculate the distance (zoom level) of the current map view.
    MKMapRect mRect = self.mapView.visibleMapRect;
    MKMapPoint eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), MKMapRectGetMidY(mRect));
    MKMapPoint westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMidY(mRect));

    //Set your current distance instance variable.
    self.currentDist = MKMetersBetweenMapPoints(eastMapPoint, westMapPoint);

    //Set your current center point on the map instance variable.
    self.currentCentre = self.mapView.centerCoordinate;

   // NSLog(@"currentCentre is (%f , %f)", self.currentCentre.latitude, self.currentCentre.longitude);

}

// Setup annotation objects
-(void)plotPositions:(NSArray *)data {
    // 1 - Remove any existing custom annotations but not the user location blue dot.

    for (id<MKAnnotation> annotation in self.mapView.annotations) {
        if ([annotation isKindOfClass:[MapPoint class]]) {
            [self.mapView removeAnnotation:annotation];
        }
    }
    // 2 - Loop through the array of places returned from the Google API.
    for (int i=0; i<[data count]; i++) {
        //Retrieve the NSDictionary object in each index of the array.
        NSDictionary* place = [data objectAtIndex:i];
        // 3 - There is a specific NSDictionary object that gives us the location info.
        NSDictionary *geo = [place objectForKey:@"geometry"];
        // Get the lat and long for the location.
        NSDictionary *loc = [geo objectForKey:@"location"];
        // 4 - Get your name and address info for adding to a pin.
        NSString *name=[place objectForKey:@"name"];
        NSString *vicinity=[place objectForKey:@"vicinity"];
        // Create a special variable to hold this coordinate info.
        CLLocationCoordinate2D placeCoord;
        // Set the lat and long.
        placeCoord.latitude=[[loc objectForKey:@"lat"] doubleValue];
        placeCoord.longitude=[[loc objectForKey:@"lng"] doubleValue];

        // 5 - Create a new annotation.
        MapPoint *placeObject = [[MapPoint alloc] initWithName:name address:vicinity coordinate:placeCoord];
        [self.mapView addAnnotation:placeObject];
    }
    NSLog(@"addAnnotation is done");

}

// Setup annotation view
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    // Define your reuse identifier.
    static NSString *identifier = @"MapPoint";

    if ([annotation isKindOfClass:[MapPoint class]]) {
        MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];

        if (annotationView == nil) {
            annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
        } else {
            annotationView.annotation = annotation;
        }
        annotationView.enabled = YES;
        annotationView.canShowCallout = YES;
        annotationView.animatesDrop = YES;


        // NSLog(@"annotation view is added");

        return annotationView;

    }
    return nil;
}

@end
4

1 回答 1

6

有几件事:

移动您的 removeAnnotation 和 addAnnotation 代码以在 UI 线程上运行,例如:

dispatch_async (dispatch_get_main_queye(), ^
{
 [self.mapView addAnnotation:placeObject]; 
});

将您的 viewWillAppear 初始化代码移动到 viewDidLoad。viewWillAppear 可能在视图控制器的生命周期内被多次调用

于 2012-08-23T16:38:47.387 回答