Загрузить только пять аннотаций в MKMapVIew - PullRequest
1 голос
/ 07 марта 2011

У меня есть 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 ]

3 голосов
/ 07 марта 2011

Длинный ответ, в основном уже написанный, когда Стивен Полетто опубликовал, и содержащий пример кода о том, как использовать встроенные методы для сортировки массива, так что я все же стоил публиковать, хотя основной ответ тот же (т. Е."выберите пять ближайших для себя, передайте только те, которые включены"):

Вам нужно будет отсортировать свои аннотации по расстоянию для себя и представить только самые близкие пять в MKMapView.Если у вас есть два CLLocations, вы можете получить расстояние между ними, используя метод distanceFromLocation: (который был getDistanceFrom: до iOS 3.2; это имя устарело).

Итак, дляНапример, предположим, что у вашего класса Annotation есть метод 'setReferenceLocation:', в который вы передаете CLLocation и получатель '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 представления карты.Если у вас достаточно много потенциальных аннотаций, то сортировка всех них немного расточительна, и вам лучше использовать quadtree или kd-tree.

2 голосов
/ 07 марта 2011

Сначала вам нужно получить текущее местоположение пользователя.Вы можете создать 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

Когда вы просматриваете свои аннотации, просто сохраните пять ближайших мест.Вы можете создать CLLocation из переменных 'lat' и 'longi', которые вы используете:

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

Надеюсь, это поможет!

...