MKAnnotation仅在区域内

发布于 2024-12-02 22:17:23 字数 3068 浏览 0 评论 0原文

如何只加载显示区域内的注释?目前,我使用此方法加载所有注释

- (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]];
}

关于如何删除显示之外的所有注释并加载其他注释,有什么想法或好的文档吗?

非常感谢

编辑:

我实际上已经找到了一个解决方案,但它在某种程度上并不完美。我检查区域是否已更改

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    [self reloadAnnotatons];
}

然后我获取最大/最小纬度/经度并将其从 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]];
}

唯一的问题是,如果放大到某个级别,它只会找到注释,这很奇怪。例如

,当我缩小很远时,它的范围从最小到最大。顺序是 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] (
)

一旦我放大它就得到了对象。虽然它之前应该已经找到了。

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>)",

当我直接对 sqllite 数据库进行 sql 查询时,它实际上找到了它,

SELECT * 
FROM caves
WHERE (
latitude > 43.930069
AND latitude < 50.169209
)
AND (
longitude > 3.078351
AND longitude < 10.207223
)

为什么是这样?

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 solution 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

鸵鸟症 2024-12-09 22:17:23

我实际上找到了所有这些问题的解决方案。我跟踪该区域是否已更改

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    [self reloadAnnotatons];
}

然后我获取最大/最小纬度/经度并将其从 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]];
}

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]];
}
归属感 2024-12-09 22:17:23

默认情况下,MapView 仅加载显示内容(即屏幕上)的注释。如果您只是移动屏幕,则可以通过注释的重用标识符来重用注释。因此从技术上讲,您不需要删除显示之外的注释。

来自苹果文档的信息

由于注释视图仅在屏幕上时才需要,因此
MKMapView 类提供了一种对注释视图进行排队的机制
未使用的。带有重用标识符的注释视图可以是
当它们离开时,由地图视图在内部分离和排队
屏幕。此功能通过仅保留一小部分来提高内存使用率
内存中的注释视图数量,并通过回收
你确实有的观点。它还通过以下方式提高了滚动性能
减少在地图滚动时创建新视图的需要。

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.

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