「カフェ」などのツールバー ボタンをクリックすると、表示されているマップ領域にカフェが表示されると思います。データは 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