MKAnnotation only within region
How can I only load the annotations that are within the displayed region? At the moment I load all Annotation with this method
- (void)reloadAnnotatons
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"Cave" inManagedObjectContext:self.context];
request.predicate = [NSPredicate predicateWithFormat:@"(latitude > 0) AND (longitude > 0)"];
[self.mapView addAnnotations:[self.context executeFetchRequest:request error:NULL]];
}
Any ideas or good documents on how I could remove all annotations that are outside the display and load the others?
Thanks a lot
EDIT:
I have actually found a solut开发者_如何学编程ion but it does not perfectly work somehow. I check if region has changed
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
[self reloadAnnotatons];
}
Then I get max/min lat/long and pull it out of coredata
- (void)reloadAnnotatons
{
double minLat = self.mapView.region.center.latitude - (self.mapView.region.span.latitudeDelta / 2);
double maxLat = self.mapView.region.center.latitude + (self.mapView.region.span.latitudeDelta / 2);
double minLon = self.mapView.region.center.longitude - (self.mapView.region.span.longitudeDelta / 2);
double maxLon = self.mapView.region.center.longitude + (self.mapView.region.span.longitudeDelta / 2);
NSLog(@"%f %f %f %f",minLat,maxLat,minLon,maxLon);
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"Cave" inManagedObjectContext:self.context];
request.predicate = [NSPredicate predicateWithFormat:@"(latitude > %f AND latitude < %f) AND (longitude > %f AND longitude < %f)",minLat,maxLat,minLon,maxLon];
//NSLog(@"%@",[self.context executeFetchRequest:request error:NULL]);
[self.mapView addAnnotations:[self.context executeFetchRequest:request error:NULL]];
}
Only problem is that it only finds the annotations if you zoom in a certain level which is strange. For example
When I zoomed out quite far it has a wide range from min to max. Order is minLat,maxLat,minLong,MaxLong
2011-09-07 08:48:15.907 CaveConditions[9028:707] 43.930069 50.169209 3.078351 10.207223
2011-09-07 08:48:15.914 CaveConditions[9028:707] (
)
As soon as I zooom in it does get the objects. Allthough it should already find it before.
2011-09-07 08:48:35.363 CaveConditions[9028:707] 46.277977 48.327505 5.453421 7.806564
2011-09-07 08:48:35.376 CaveConditions[9028:707] (
"<Cave: 0x1d8710> (entity: Cave; id: 0x1cdd10 <x-coredata://738720B4-DCF4-40BA-BD83-A459CECE5F29/Cave/p2> ; data: <fault>)",
"<Cave: 0x1941c0> (entity: Cave; id: 0x1d1e70 <x-coredata://738720B4-DCF4-40BA-BD83-A459CECE5F29/Cave/p47> ; data: <fault>)",
"<Cave: 0x190200> (entity: Cave; id: 0x1e62b0 <x-coredata://738720B4-DCF4-40BA-BD83-A459CECE5F29/Cave/p57> ; data: <fault>)",
"<Cave: 0x1e4960> (entity: Cave; id: 0x1a1560 <x-coredata://738720B4-DCF4-40BA-BD83-A459CECE5F29/Cave/p67> ; data: <fault>)",
It actually finds it when I sql directly the sqllite db with
SELECT *
FROM caves
WHERE (
latitude > 43.930069
AND latitude < 50.169209
)
AND (
longitude > 3.078351
AND longitude < 10.207223
)
Why is that?
I actually find the solution to all of that. I track if the region has changed
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
[self reloadAnnotatons];
}
Then I get max/min lat/long and pull it out of coredata
- (void)reloadAnnotatons
{
double minLat = self.mapView.region.center.latitude - (self.mapView.region.span.latitudeDelta / 2);
double maxLat = self.mapView.region.center.latitude + (self.mapView.region.span.latitudeDelta / 2);
double minLon = self.mapView.region.center.longitude - (self.mapView.region.span.longitudeDelta / 2);
double maxLon = self.mapView.region.center.longitude + (self.mapView.region.span.longitudeDelta / 2);
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"Cave" inManagedObjectContext:self.context];
request.predicate = [NSPredicate predicateWithFormat:@"(latitude > %lf AND latitude < %lf) AND (longitude > %lf AND longitude < %lf)",minLat,maxLat,minLon,maxLon];
[self.mapView addAnnotations:[self.context executeFetchRequest:request error:NULL]];
}
As default MapView loads only the annotations that are within your display(i.e, Onscreen). If you just move the screen you can reuse the Annotations with Reuse identifier for annotations. So technically you dont need remove annotations that are out of your display.
Info from Apple doc
Because annotation views are needed only when they are onscreen, the MKMapView class provides a mechanism for queueing annotation views that are not in use. Annotation views with a reuse identifier can be detached and queued internally by the map view when they move off screen. This feature improves memory use by keeping only a small number of annotation views in memory at once and by recycling the views you do have. It also improves scrolling performance by alleviating the need to create new views while the map is scrolling.
精彩评论