我想填充一個MKMapView,當用戶滾動瀏覽地圖時可以看到無數的註釋。很明顯,用戶必須放大到足以讓視圖出現,因爲如果不是,應用程序處理太多,每次只顯示約20個視圖。帶有無限的隨機註釋的MKMapView
我有一個約100個對象的數組,我需要隨機地在整個地圖上隨機重複。這些是在運行時使用MKMapView的visibleMapRect屬性創建的,只創建必要的。我還實現了一個緩存字典來防止重新創建以前創建的對象。這裏是我的簡化當前的代碼:
@property (nonatomic, strong) NSArray *mapObjects; //Contains 100 objects to be repeated
@property (nonatomic, strong) NSMutableDictionary *cache; //Cache already created mapObjects
//Constants used
int const MapDensity = 5000.0; //Density of annotations
int const MapZoomMax = 30000.0; //Max zoom level to show annotations
- (void)loadLocations {
MKMapRect rect = [mapView visibleMapRect];
if (rect.size.width > MapZoomMax) {
[self performSelectorOnMainThread:@selector(removeAllAnnotations) withObject:nil waitUntilDone:NO];
return;
}
rect.origin.x = MapDensity*floor(rect.origin.x/MapDensity);
rect.origin.y = MapDensity*floor(rect.origin.y/MapDensity);
MKMapPoint pointLocation = rect.origin;
NSMutableArray *locationsArray = [NSMutableArray array];
while (pointLocation.y < rect.origin.y+rect.size.height) {
while (pointLocation.x < rect.origin.x+rect.size.width) {
int cacheKey = pointLocation.x*pointLocation.y;
if (![self.cache objectForKey:[NSNumber numberWithInt:cacheKey]]) {
//Adjust for randomness
MKMapPoint pointLocationAdjusted = pointLocation;
pointLocationAdjusted.x += arc4random()%MapDensity;
pointLocationAdjusted.y += arc4random()%MapDensity;
//Create annotation
GLAnnotation *annotation = [[GLAnnotation alloc] init];
[annotation setCoordinate:MKCoordinateForMapPoint(pointLocationAdjusted)];
[annotation setMapObject:[self.mapObjects objectAtIndex:(arc4random()%[mapObjects count])]];
[locationsArray addObject:annotation];
[self.cache setObject:annotation forKey:[NSNumber numberWithInt:cacheKey]];
} else {
[locationsArray addObject:[self.cache objectForKey:[NSNumber numberWithInt:cacheKey]]];
}
pointLocation.x += MapDensity; //Go to next X
}
pointLocation.x = rect.origin.x; //Restart X
pointLocation.y += MapDensity; //Go to next Y
}
[self performSelectorOnMainThread:@selector(addAnnotations:) withObject:locationsArray waitUntilDone:NO];
}
- (void)addAnnotations:(NSArray *)annotations {
NSMutableArray *newAnnotations = [NSMutableArray array];
for (id annotation in annotations) {
if (![mapView.annotations containsObject:annotation]) {
[mapView addObject:annotation];
}
}
[mapView addAnnotations:newAnnotations];
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
[self performSelectorInBackground:@selector(loadLocations) withObject:nil];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
if([annotation isKindOfClass:[GLAnnotation class]]){
static NSString *annotationIdentifier = @"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
if(!annotationView){
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
annotationView.canShowCallout = YES;
}
annotationView.image = [(GLAnnotation *)annotation picture];
return annotationView;
}
return nil;
}
代碼似乎工作的大部分時間,但它有時會使地圖滾動滯後(我試圖修復在後臺線程中運行它),通常使應用程序崩潰,似乎是由內存問題(我嘗試使用緩存修復)引起的。不輸出任何錯誤消息,除了:EXC_BAD_ACCESS。如果有人能告訴我如何正確管理這些註釋,我將非常感激。
是的,你是對的緩存錯誤。這部分似乎工作正常,所以我沒有注意到,但如果用戶在一些敏感的地方,它很容易被注意到。謝謝! – gabriellanata
在第一部分中,我添加了下面的代碼來移動起點,但我仍然得到了很多內存錯誤: 'rect.origin.x - = MapDensity * floor(rect.origin.x/MapDensity);' 'rect.origin.y - = MapDensity * floor(rect.origin.y/MapDensity);' – gabriellanata
看起來你正在穿過你的流。 regionDidChangeAnimated調用發生在ui線程上,然後在後臺線程上loadLocations,但它將刪除註釋並將其添加到mapview,因此它應該在主線程/ ui線程上。什麼是locationsMap? – Craig