MKMapView 一次加载所有注释视图(包括当前矩形之外的注释视图)

发布于 2024-07-30 19:55:50 字数 2168 浏览 6 评论 0原文

更新

看来这个问题已经在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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝天 2024-08-06 19:55:50

您所期望的是基于地图显示的当前区域对注释视图进行某种“剪辑”。

这不是 dequeueReusableAnnotationViewWithIdentifier 选择器的工作方式。

从它的文档来看:
当注释视图移出屏幕时,地图视图会将它们移动到内部管理的重用队列中。 当新注释在屏幕上移动时,系统会提示您的代码提供相应的注释视图,您应该始终尝试在创建新视图之前使现有视图出列。

因此,可重用机制仅在您调用如下序列时才有意义:

//this will create 1000 annotation views
[theMap addAnnotations:my1000annotations];
//this will move them offscreen (but some annotation views may be kept internally for further reuse)
[theMap removeAnnotatios:theMap.annotations];
//when adding back again some annotations onscreen, some of the previous annotation views will be reused.
[theMap addAnnotations:someNew400annotations];

在您的情况下,我实现剪辑的方式(仅显示当前显示区域的注释)是:

  • 将委托添加到您的mapView并实现- (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 :


//this will create 1000 annotation views
[theMap addAnnotations:my1000annotations];
//this will move them offscreen (but some annotation views may be kept internally for further reuse)
[theMap removeAnnotatios:theMap.annotations];
//when adding back again some annotations onscreen, some of the previous annotation views will be reused.
[theMap addAnnotations:someNew400annotations];

In you case, the way I would implement the clipping (to display only the annotation for the current displayed region) is :


  • Add a delegate to your mapView and implement the - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated method to get informed when the region has changed

  • iterate through all your objects to get the ones that match this region

  • addAnnotations to your map for only those objects (you can implement a kind of merge between the previously displayed annotations and the new one or simply restart from scratch , remove all annotations, and set the new ones

Of 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... ;)

神回复 2024-08-06 19:55:50

不确定这是否有帮助,但您提到了由于加载约 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?

// :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文