MKPolyline не отображается в MKMapView

Вот код. Это довольно прямолинейно. Я делаю путь для того, кто идет. Итак, вот код моего файла ViewController.m:

#import "ViewController.h"

@interface ViewController ()

@property BOOL firstTime;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self.mapView setDelegate:self];
    [self.mapView setShowsUserLocation:YES];
    [self.mapView setMapType:MKMapTypeHybrid];

    [self setLocationManager:[[CLLocationManager alloc] init]];
    [self.locationManager setDelegate:self];
    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locationManager startUpdatingLocation];

    self.index = 0;

    self.firstTime = YES;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    if(self.firstTime)
    {
        CLLocation *startingLocation = [locations objectAtIndex:0];
        self.startingPointCooridinates = startingLocation.coordinate;
        self.index++;

        MKPointAnnotation *startingPointAnnotation = [[MKPointAnnotation alloc] init];
        startingPointAnnotation.title = @"Starting Point";
        startingPointAnnotation.coordinate = startingLocation.coordinate;

        [self.mapView addAnnotation:startingPointAnnotation];

        self.firstTime = false;
    }

    [self.locations addObject:[locations objectAtIndex:0]];

    CLLocationCoordinate2D coordinates[[self.locations count]];
    for(int i = 0; i < self.locations.count; i++)
    {
        CLLocation *currentLocation = [locations objectAtIndex:i];
        coordinates[i] = currentLocation.coordinate;
    }

    MKPolyline *pathPolyline = [MKPolyline polylineWithCoordinates:coordinates count:self.locations.count];
    [self.mapView addOverlay:pathPolyline];
}

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
    if([overlay isKindOfClass:[MKPolyline class]])
    {
        MKPolylineRenderer *polylineRenderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
        polylineRenderer.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.2];
        polylineRenderer.strokeColor = [[UIColor redColor] colorWithAlphaComponent:0.7];
        polylineRenderer.lineWidth = 2.0;
        return polylineRenderer;
    }
    else
    {
        return  nil;
    }
}

Теперь отображается только аннотация, а MKPolyline не отображается. Что я делаю неправильно ? Спасибо.


person Objective-J    schedule 21.12.2013    source источник
comment
Вы проверяли содержимое self.locations? Правильно ли добавляются координаты в self.locations? Насколько я знаю, проблема связана с тем, что метод MKPolyline polylineWithCoordinates вызывается с неправильным параметром count.   -  person Uygar Y    schedule 21.12.2013
comment
Вы выделили + инициализировали self.locations? Вы работаете на iOS 7? Кстати, вы должны сделать removeOverlays перед добавлением, потому что прямо сейчас код добавляет новый оверлей, который на один сегмент длиннее предыдущих (которые рисуются под последним). Не имеет отношения, но обратите внимание, что fillColor не влияет на полилинию (нужен только strokeColor).   -  person    schedule 21.12.2013
comment
Как указывает Анна, вы должны установить strokeColor, а не fillColor.   -  person Rob    schedule 21.12.2013
comment
@Anna - Как удалить предыдущий оверлей?!   -  person Objective-J    schedule 21.12.2013
comment
@ Анна - Ты был прав. Я забыл alloc init массив местоположений. Спасибо. Но как удалить последний оверлей?   -  person Objective-J    schedule 21.12.2013


Ответы (1)


  1. Как упоминалось в комментариях, ваш массив locations никогда не выделяется и не инициализируется, поэтому он nil и вызовы к нему (например, addObject) ничего не делают, и поэтому ломаная линия никогда не добавляет к ней никаких координат (и поэтому она не отображается).

    В viewDidLoad перед запуском CLLocationManager выделите и инициализируйте массив:

    self.locations = [NSMutableArray array];
    
  2. Другая проблема, с которой вы столкнетесь, связана с этой строкой в ​​didUpdateLocations в цикле for:

    CLLocation *currentLocation = [locations objectAtIndex:i];
    

    Здесь locations (без self.) относится к локальной переменной параметра метода делегата, а не к вашей locations переменной свойства уровня экземпляра класса. Компилятор должен предупредить вас об этом сообщением типа «Локальное объявление« местоположения »скрывает переменную экземпляра».

    В этом случае предупреждение имеет решающее значение. Что вы действительно хотите сделать здесь, так это сослаться на переменную свойства locations, где вы храните полный след пользователя с координатами, а не на локальную переменную, которая имеет только последние x незарегистрированных местоположений (обычно только 1 объект).

    Поэтому эту строку следует изменить на:

    CLLocation *currentLocation = [self.locations objectAtIndex:i];
    

    Было бы лучше, если бы вы просто использовали имя, отличное от locations, чтобы избежать этих проблем.

  3. Как также упоминалось в комментариях, поскольку вы добавляете наложение с полным следом движения пользователя каждый раз, когда пользователь перемещается, вам необходимо сначала удалить предыдущее наложение. В противном случае вы без необходимости будете добавлять несколько наложений на карту, поскольку последнее наложение покрывает все движение. Предыдущие наложения явно не видны, поскольку они имеют те же координаты, тот же цвет и ту же ширину линии. Итак, прежде чем вызывать addOverlay, проще всего вызвать removeOverlays с текущим списком оверлеев карты:

    //remove any previous overlays first...
    [self.mapView removeOverlays:mapView.overlays];
    
    //now add overlay with the updated trail...
    [self.mapView addOverlay:pathPolyline];
    
  4. Незначительный момент, не влияющий на отображение, заключается в том, что установка fillColor для полилинии не имеет никакого эффекта. Вам нужно только установить strokeColor, что делает код. Вы можете удалить вызов для установки fillColor.

  5. Наконец, вас может заинтересовать пример приложения Apple Breadcrumb. В их версии используется пользовательское наложение, которое можно динамически обновлять без необходимости удалять и добавлять наложения каждый раз при изменении или добавлении.

person Community    schedule 21.12.2013
comment
Большое спасибо Анна! Это просто идеально. - person Objective-J; 22.12.2013