"카페"와 같은 툴바 버튼을 한 번 클릭하면 카페가 보이는지도 영역에 표시됩니다. Google Places API에서 데이터를 가져옵니다. 단추를 클릭 한 후 핀이 표시되지 않는 것을 제외하면 모두 잘 작동합니다.MapKit :지도를 스크롤 할 때까지 주석보기가 표시되지 않습니다.
확실한 지연 시간이 예상됩니다. 그러나 백그라운드 대기열에서 페치를 수행하고 기다리는 동안 회전하는 바퀴를 놓고 페칭 및 구문 분석이 완료되면 회전하는 바퀴가 숨겨집니다. 따라서 나는 회전하는 바퀴가 사라지는 순간에 데이터가 있다고 확신합니다. 그러나지도를 스크롤 할 때까지 핀이 나타나지 않습니다.
나는 스크롤 맵이 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
감사합니다. 문제가 쭈그러 들었습니다 :) 주 스레드에서 실행되는 코드를 수정 해 넣으십시오. – Philip007
아마도 메인 스레드에서 plotPositions를 호출하고 더 깨끗하게 만들 수 있습니다. – CSmith
맞습니다. 이를 위해 NSArray를 @property로 추가하여 응답 데이터를 저장합니다. 따라서 plotPositions와 parseData는 중첩되는 대신 서로 분리 될 수 있습니다. 그런 다음 배경 큐에 parseData를 배치하고 주 큐에 plotPositions를 배치했습니다. 훨씬 깨끗해 보입니다. 귀하의 소중한 조언에 감사드립니다. – Philip007