仅将五个注释加载到 MKMapVIew

发布于 2024-10-20 11:32:20 字数 1867 浏览 2 评论 0原文

我有一个 MKMapView,我想知道如何找到距离用户最近的 5 个注释,并只将它们显示在 MKMapView 上。

我的代码目前是:

- (void)loadFiveAnnotations {
    NSString *string = [[NSString alloc] initWithContentsOfURL:url];
    string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    NSArray *chunks = [string componentsSeparatedByString:@";"];
    NSArray *keys = [NSArray arrayWithObjects:@"type", @"name", @"street", @"address1", @"address2", @"town", @"county", @"postcode", @"number", @"coffeeclub", @"latlong", nil];   
    // max should be a multiple of 12 (number of elements in keys array)
    NSUInteger max = [chunks count] - ([chunks count] % [keys count]);
    NSUInteger i = 0;

    while (i < max)
    {
        NSArray *subarray = [chunks subarrayWithRange:NSMakeRange(i, [keys count])];
        NSDictionary *dict = [[NSDictionary alloc] initWithObjects:subarray forKeys:keys];
        // do something with dict
        NSArray *latlong = [[dict objectForKey:@"latlong"] componentsSeparatedByString:@","];
        NSString *latitude = [[latlong objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        NSString *longitude = [[latlong objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        CLLocationDegrees lat = [latitude floatValue];
        CLLocationDegrees longi = [longitude floatValue];
        Annotation *annotation = [[Annotation alloc] initWithCoordinate:CLLocationCoordinate2DMake(lat, longi)];
        annotation.title = [dict objectForKey:@"name"];
        annotation.subtitle = [NSString stringWithFormat:@"%@, %@, %@",[dict objectForKey:@"street"],[dict objectForKey:@"county"], [dict objectForKey:@"postcode"]];
        [mapView addAnnotation:annotation];
        [dict release];

        i += [keys count];
    }
}

I have a MKMapView, and I would like to know how I can find the nearest 5 annotations to the user, and only display them on the MKMapView.

My code currently is:

- (void)loadFiveAnnotations {
    NSString *string = [[NSString alloc] initWithContentsOfURL:url];
    string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    NSArray *chunks = [string componentsSeparatedByString:@";"];
    NSArray *keys = [NSArray arrayWithObjects:@"type", @"name", @"street", @"address1", @"address2", @"town", @"county", @"postcode", @"number", @"coffeeclub", @"latlong", nil];   
    // max should be a multiple of 12 (number of elements in keys array)
    NSUInteger max = [chunks count] - ([chunks count] % [keys count]);
    NSUInteger i = 0;

    while (i < max)
    {
        NSArray *subarray = [chunks subarrayWithRange:NSMakeRange(i, [keys count])];
        NSDictionary *dict = [[NSDictionary alloc] initWithObjects:subarray forKeys:keys];
        // do something with dict
        NSArray *latlong = [[dict objectForKey:@"latlong"] componentsSeparatedByString:@","];
        NSString *latitude = [[latlong objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        NSString *longitude = [[latlong objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        CLLocationDegrees lat = [latitude floatValue];
        CLLocationDegrees longi = [longitude floatValue];
        Annotation *annotation = [[Annotation alloc] initWithCoordinate:CLLocationCoordinate2DMake(lat, longi)];
        annotation.title = [dict objectForKey:@"name"];
        annotation.subtitle = [NSString stringWithFormat:@"%@, %@, %@",[dict objectForKey:@"street"],[dict objectForKey:@"county"], [dict objectForKey:@"postcode"]];
        [mapView addAnnotation:annotation];
        [dict release];

        i += [keys count];
    }
}

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

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

发布评论

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

评论(2

真心难拥有 2024-10-27 11:32:20

一个很长的答案,大部分是在 Stephen Poletto 发布时写的,并包含有关如何使用内置方法对数组进行排序的示例代码,所以我认为它仍然值得发布,尽管基本答案是相同的(即“选择五个最接近您自己的,仅传递那些”):

您将需要为自己按距离对注释进行排序,并仅将最接近的五个提交到 MKMapView。如果您有两个 CLLocation,则可以使用 distanceFromLocation: 方法(在 iOS 3.2 之前为 getDistanceFrom:;该名称现已弃用)。

因此,例如,假设您的 Annotation 类有一个方法“setReferenceLocation:”,您可以向该方法传递一个 CLLocation 和一个 getter“distanceFromReferenceLocation”,该方法返回两者之间的距离,您可以这样做:

// create and populate an array containing all potential annotations
NSMutableArray *allPotentialAnnotations = [NSMutableArray array];

for(all potential annotations)
{
    Annotation *annotation = [[Annotation alloc]
                                            initWithCoordinate:...whatever...];
    [allPotentialAnnotations addObject:annotation];
    [annotation release];
}

// set the user's current location as the reference location
[allPotentialAnnotations
      makeObjectsPerformSelector:@selector(setReferenceLocation:) 
      withObject:mapView.userLocation.location];

// sort the array based on distance from the reference location, by
// utilising the getter for 'distanceFromReferenceLocation' defined
// on each annotation (note that the factory method on NSSortDescriptor
// was introduced in iOS 4.0; use an explicit alloc, init, autorelease
// if you're aiming earlier)
NSSortDescriptor *sortDescriptor = 
              [NSSortDescriptor
                  sortDescriptorWithKey:@"distanceFromReferenceLocation" 
                  ascending:YES];

[allPotentialAnnotations sortUsingDescriptors:
                          [NSArray arrayWithObject:sortDescriptor]];

// remove extra annotations if there are more than five
if([allPotentialAnnotations count] > 5)
{
    [allPotentialAnnotations
               removeObjectsInRange:NSMakeRange(5, 
                           [allPotentialAnnotations count] - 5)];
}

// and, finally, pass on to the MKMapView
[mapView addAnnotations:allPotentialAnnotations];

根据您加载的位置,您需要为注释创建本地存储(在内存中或磁盘上),并在用户移动时选择五个最近的存储。将自己注册为 CLLocationManager 委托或地图视图的 userLocation 属性上的键值观察。如果您有相当多的潜在注释,那么对所有注释进行排序有点浪费,最好建议您使用四叉树或 kd 树。

A long answer, already mostly written when Stephen Poletto posted and containing example code on how to use the built-in methods for sorting an array, so I though it was still worth posting though the essential answer is the same (ie, "pick the five closest for yourself, pass only those on"):

You're going to need to sort your annotations by distance for yourself, and submit only the closest five to the MKMapView. If you have two CLLocations then you can get the distance between them using the distanceFromLocation: method (which was getDistanceFrom: prior to iOS 3.2; that name is now deprecated).

So, for example, supposing your Annotation class had a method 'setReferenceLocation:' to which you pass a CLLocation and a getter 'distanceFromReferenceLocation' which returns the distance between the two, you could do:

// create and populate an array containing all potential annotations
NSMutableArray *allPotentialAnnotations = [NSMutableArray array];

for(all potential annotations)
{
    Annotation *annotation = [[Annotation alloc]
                                            initWithCoordinate:...whatever...];
    [allPotentialAnnotations addObject:annotation];
    [annotation release];
}

// set the user's current location as the reference location
[allPotentialAnnotations
      makeObjectsPerformSelector:@selector(setReferenceLocation:) 
      withObject:mapView.userLocation.location];

// sort the array based on distance from the reference location, by
// utilising the getter for 'distanceFromReferenceLocation' defined
// on each annotation (note that the factory method on NSSortDescriptor
// was introduced in iOS 4.0; use an explicit alloc, init, autorelease
// if you're aiming earlier)
NSSortDescriptor *sortDescriptor = 
              [NSSortDescriptor
                  sortDescriptorWithKey:@"distanceFromReferenceLocation" 
                  ascending:YES];

[allPotentialAnnotations sortUsingDescriptors:
                          [NSArray arrayWithObject:sortDescriptor]];

// remove extra annotations if there are more than five
if([allPotentialAnnotations count] > 5)
{
    [allPotentialAnnotations
               removeObjectsInRange:NSMakeRange(5, 
                           [allPotentialAnnotations count] - 5)];
}

// and, finally, pass on to the MKMapView
[mapView addAnnotations:allPotentialAnnotations];

Depending on where you're loading from, you made need to create a local store (in memory or on disk) for annotations and select the five nearest whenever the user moves. Either register yourself as a CLLocationManager delegate or key-value observe on the map view's userLocation property. If you have quite a lot of potential annotations then sorting all of them is a bit wasteful and you'd be better advised to use a quadtree or a kd-tree.

拥有 2024-10-27 11:32:20

首先,您需要获取用户的当前位置。您可以构建一个 CLLocationManager 并将自己注册为位置更新的委托,如下所示:

locationManager = [[[CLLocationManager alloc] init] autorelease];
[locationManager setDelegate:self];
[locationManager startUpdatingLocation];

将自己设置为委托后,您将收到以下回调:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

现在您拥有了用户的位置(newLocation),您可以找到五个最接近的注释。 CoreLocation 中有一个方便的方法:

- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location

当您迭代注释时,只需存储五个最近的位置即可。您可以使用您使用的“lat”和“longi”变量构建 CLLocation:

- (id)initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude

希望这会有所帮助!

First you'll need to grab the user's current location. You can build a CLLocationManager and register yourself as the delegate for location updates as follows:

locationManager = [[[CLLocationManager alloc] init] autorelease];
[locationManager setDelegate:self];
[locationManager startUpdatingLocation];

After setting yourself as the delegate, you'll receive the following callback:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

Now that you have the user's location (newLocation), you can find the five closest annotations. There is a handy method in CoreLocation:

- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location

As you're iterating through your annotations, just store the five nearest locations. You can build a CLLocation out of the 'lat' and 'longi' variables you have using:

- (id)initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude

Hope this helps!

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