仅向MKMapVIew加载五个注释

时间:2011-03-07 17:43:15

标签: iphone objective-c xcode ios4 mkmapview

我有一个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];
    }
}

2 个答案:

答案 0 :(得分:3)

一个很长的答案,主要是在Stephen Poletto发布并包含如何使用内置方法对数组进行排序的示例代码时编写的,所以尽管基本答案是相同的(即, “为自己选择最接近的五个,只通过那些”):

您需要为自己按距离对注释进行排序,并仅向MKMapView提交最接近的五个注释。如果您有两个CLLocations,那么您可以使用distanceFromLocation:方法获取它们之间的距离(这是getDistanceFrom:在iOS 3.2之前;该名称现已弃用)。

因此,例如,假设您的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];

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

答案 1 :(得分:2)

首先,您需要获取用户的当前位置。您可以构建一个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

希望这有帮助!