MKMapView 一次加载所有注释视图(包括当前矩形之外的注释视图)
更新
看来这个问题已经在iOS 4.3中悄然修复了。 到目前为止,即使放大得非常近,被认为“足够远”以便回收注释的距离似乎也有数百英里。 当我使用 iOS 4.3 SDK 构建应用程序时,注释将根据更合理的限制进行回收。
还有其他人遇到过这个问题吗? 代码如下:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(WWMapAnnotation *)annotation {
// Only return an Annotation view for the placemarks. Ignore for the current location--the iPhone SDK will place a blue ball there.
NSLog(@"Request for annotation view");
if ([annotation isKindOfClass:[WWMapAnnotation class]]){
MKPinAnnotationView *browse_map_annot_view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"BrowseMapAnnot"];
if (!browse_map_annot_view) {
browse_map_annot_view = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"BrowseMapAnnot"] autorelease];
NSLog(@"Creating new annotation view");
} else {
NSLog(@"Recycling annotation view");
browse_map_annot_view.annotation = annotation;
}
...
一旦显示视图,我就会不断
2009-08-05 13:12:03.332 xxx[24308:20b] Request for annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Creating new annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Request for annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Creating new annotation view
地为我添加的每个注释(~60)进行操作。 地图(正确地)仅显示当前矩形中的两个注释。 我正在 viewDidLoad 中设置区域:
if (center_point.latitude == 0) {
center_point.latitude = 35.785098;
center_point.longitude = -78.669899;
}
if (map_span.latitudeDelta == 0) {
map_span.latitudeDelta = .001;
map_span.longitudeDelta = .001;
}
map_region.center = center_point;
map_region.span = map_span;
NSLog(@"Setting initial map center and region");
[browse_map_view setRegion:map_region animated:NO];
在请求任何注释视图之前,正在设置的区域的日志条目将打印到控制台。
这里的问题是,由于同时请求所有注释,因此 [mapView dequeueReusableAnnotationViewWithIdentifier] 不执行任何操作,因为地图上的每个注释都有唯一的 MKAnnotationView。 这导致了我的记忆问题。
一个可能的问题是这些注释聚集在一个相当小的空间(半径约 1 英里)内。 尽管地图在 viewDidLoad 中放大得非常紧密(纬度和经度增量 0.001),但它仍然会立即加载所有注释视图。
谢谢...
UPDATE
It looks like this problem has been quietly fixed in iOS 4.3. Up to this point, the distance that was considered "far enough" for an annotation to be recycled seemed to be hundreds of miles, even when zoomed in very closely. When I build my app with the iOS 4.3 SDK, annotations are recycled based on more reasonable limits.
Has anyone else run into this problem? Here's the code:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(WWMapAnnotation *)annotation {
// Only return an Annotation view for the placemarks. Ignore for the current location--the iPhone SDK will place a blue ball there.
NSLog(@"Request for annotation view");
if ([annotation isKindOfClass:[WWMapAnnotation class]]){
MKPinAnnotationView *browse_map_annot_view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"BrowseMapAnnot"];
if (!browse_map_annot_view) {
browse_map_annot_view = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"BrowseMapAnnot"] autorelease];
NSLog(@"Creating new annotation view");
} else {
NSLog(@"Recycling annotation view");
browse_map_annot_view.annotation = annotation;
}
...
As soon as the view is displayed, I get
2009-08-05 13:12:03.332 xxx[24308:20b] Request for annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Creating new annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Request for annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Creating new annotation view
and on and on, for every annotation (~60) I've added. The map (correctly) only displays the two annotations in the current rect. I am setting the region in viewDidLoad:
if (center_point.latitude == 0) {
center_point.latitude = 35.785098;
center_point.longitude = -78.669899;
}
if (map_span.latitudeDelta == 0) {
map_span.latitudeDelta = .001;
map_span.longitudeDelta = .001;
}
map_region.center = center_point;
map_region.span = map_span;
NSLog(@"Setting initial map center and region");
[browse_map_view setRegion:map_region animated:NO];
The log entry for the region being set is printed to the console before any annotation views are requested.
The problem here is that since all of the annotations are being requested at once, [mapView dequeueReusableAnnotationViewWithIdentifier] does nothing, since there are unique MKAnnotationViews for every annotation on the map. This is leading to memory problems for me.
One possible issue is that these annotations are clustered in a pretty small space (~1 mile radius). Although the map is zoomed in pretty tight in viewDidLoad (latitude and longitude delta .001), it still loads all of the annotation views at once.
Thanks...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您所期望的是基于地图显示的当前
区域
对注释视图进行某种“剪辑”。这不是 dequeueReusableAnnotationViewWithIdentifier 选择器的工作方式。
从它的文档来看:
当注释视图移出屏幕时,地图视图会将它们移动到内部管理的重用队列中。 当新注释在屏幕上移动时,系统会提示您的代码提供相应的注释视图,您应该始终尝试在创建新视图之前使现有视图出列。
因此,可重用机制仅在您调用如下序列时才有意义:
在您的情况下,我实现剪辑的方式(仅显示当前显示区域的注释)是:
- (void)mapView:(MKMapView *)mapView RegionDidChangeAnimated:(BOOL)animated
方法,以便在区域发生更改时获得通知当然,当用户缩小了很多并且该区域的范围太大(要显示的引脚太多),那么您必须做出决定:我是否显示所有注释视图(并冒着显示在屏幕上的风险)地图没有提供太多信息)或者我是否向用户设置一条消息说“放大以获取图钉”或其他什么,但这是另一个故事......;)
What you would expect is some kind of "clipping" of the annotation views based on the current
region
the map displays.This is NOT the way the
dequeueReusableAnnotationViewWithIdentifier
selector works.From its documentation :
As annotation views move offscreen, the map view moves them to an internally managed reuse queue. As new annotations move onscreen, and your code is prompted to provide a corresponding annotation view, you should always attempt to dequeue an existing view before creating a new one.
So the reusable mechanism only makes sense when you invoke a sequence like :
In you case, the way I would implement the clipping (to display only the annotation for the current displayed region) is :
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
method to get informed when the region has changedOf course, when the user zooms out quite a lot and that the scope of the region is too big (too many pins to be displayed), then you have to take a decision : do I displayed all the annotations views (and take the risk that the display on the map does not give much info) or do I set a message to the user saying "zoom in to get pins" or whatever. But this is another story... ;)
不确定这是否有帮助,但您提到了由于加载约 60 个对象而导致的内存问题。 有没有办法根据当前地图区域中心和当前地图区域跨度有条件地加载每个对象?
// :)
Not sure if this will help, but you mentioned memory issues due to load of ~60 objects. Is there a way to conditionally load each object based on the current map region center and current map region span?
// :)