MKMapView一次加载所有注释视图(包括那些在当前rect之外的) [英] MKMapView loading all annotation views at once (including those that are outside the current rect)

查看:138
本文介绍了MKMapView一次加载所有注释视图(包括那些在当前rect之外的)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UPDATE



看起来这个问题已在iOS 4.3中悄悄解决。到目前为止,被认为足够的注释被回收利用的距离似乎是几百英里,即使放大非常接近。当我使用iOS 4.3 SDK构建我的应用程序时,注释会根据更合理的限制进行回收。






进入这个问题?代码如下:

   - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(WWMapAnnotation *)annotation {



//只返回地标的注释视图。忽略当前位置 - iPhone SDK将放置一个蓝色的球。

NSLog(@请求注释视图);

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(@创建新的注释视图);
} else {
NSLog(@Recycling annotation view);
browse_map_annot_view.annotation = annotation;
}

...



显示视图后,我会收到

  2009-08-05 13:12:03.332 xxx [24308: 20b]请求注释视图
2009-08-05 13:12:03.333 xxx [24308:20b]创建新的注释视图
2009-08-05 13:12:03.333 xxx [24308:20b]请求注释视图
2009-08-05 13:12:03.333 xxx [24308:20b]创建新的注释视图

和on和on,对于我添加的每个注释(〜60)。地图(正确)只显示当前rect中的两个注释。我在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(@设置初始地图中心和区域);

[browse_map_view setRegion:map_region animated:NO];

在请求注释视图之前,将要设置的区域的日志条目将打印到控制台。 / p>

这里的问题是,由于所有注释都被一次请求,[mapView dequeueReusableAnnotationViewWithIdentifier]不会执行任何操作,因为地图上的每个注释都有唯一的MKAnnotationView。这会导致我的记忆问题。



一个可能的问题是这些注释聚集在一个相当小的空间(〜1英里半径)。虽然地图在viewDidLoad(纬度和经度delta .001)中缩放得相当紧凑,但它仍会一次加载所有注释视图。



感谢...

解决方案

基于当前区域的注释视图的剪辑类型。



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



从其文档:
当注释视图移出屏幕时,地图视图将它们移动到内部管理的重复使用队列。当新注释在屏幕上移动时,系统会提示您的代码提供相应的注释视图,因此您应该在创建新视图之前尝试对其进行出队。



因此,当您调用序列时,可重用机制才有意义:

 
/ /这将创建1000个注释视图
[theMap addAnnotations:my1000annotations];
//这将移动它们在屏幕外(但是一些注释视图可以在内部保留以便进一步重用)
[theMap removeAnnotatios:theMap.annotations];
//在屏幕上再次添加一些注释时,以前的一些注释视图将被重用。
[theMap addAnnotations:someNew400annotations];



在这种情况下,我将实现剪辑对于当前显示的区域)是:$​​ b $ b


  • 向您的mapView添加一个委托并实现 - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated: (BOOL)动画方法以获得区域更改时的通知

  • 遍历所有对象以获取与此区域匹配的对象

  • 只向那些对象的地图添加注释(您可以在之前显示的注释和新的注释之间实现一种合并,或者从头开始重新启动,删除所有注释,然后设置新注释。



当然,当用户缩小很多,并且区域的范围太大),那么你必须做出一个决定:我显示所有的注释视图(并冒险在地图上的显示没有给出很多信息)或者我设置一个消息给用户说放大以获得引脚 管他呢。但这是另一个故事...;)


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...

解决方案

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

这篇关于MKMapView一次加载所有注释视图(包括那些在当前rect之外的)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆