在地图上使用MKPolyline绘制用户的路径

3

我是一名新手Objective-C。

在我的应用程序中,我正在尝试将用户的路线绘制在地图上。

以下是目前我只能获取用户当前位置的代码:

#import "StartCycleViewController.h"
#import "CrumbPath.h"


@interface StartCycleViewController ()

@property (nonatomic, strong) CLLocationManager *locationManager;

@property (nonatomic, strong) IBOutlet MKMapView *map;

@property (nonatomic, strong) UIView *containerView;





@end

@implementation StartCycleViewController

@synthesize cycleLocation = _cycleLocation;
@synthesize currentCycleLocation = _currentCycleLocation;






 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
 {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    // Custom initialization
    }
    return self;
 }

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self startCycleLocation];

    _containerView = [[UIView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:self.containerView];

    [self.containerView addSubview:self.map];
    // Do any additional setup after loading the view.
}


- (void)dealloc
{
    self.locationManager.delegate = nil;
}


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


#pragma mark - startCycleLocation

- (void)startCycleLocation{

    if (!_cycleLocation){
        _cycleLocation = [[CLLocationManager alloc]init];
        _cycleLocation.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
        _cycleLocation.distanceFilter = 10;
        _cycleLocation.delegate = self;

    }
    [_cycleLocation startUpdatingLocation];

}

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

    NSLog(@"didUpdateToLocation: %@", newLocation);
    CLLocation *currentLocation = newLocation;

    if (currentLocation != nil) {
    self.longitudeLabel.text = [NSString stringWithFormat:@"%.8f",    currentLocation.coordinate.longitude];
    self.latitudeLabel.text = [NSString stringWithFormat:@"%.8f",    currentLocation.coordinate.latitude];

    }
}



- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"%@",error);

    if ( [error code] != kCLErrorLocationUnknown ){
        [self stopLocationManager];
    }
}

- (void) stopLocationManager {
    [self.cycleLocation stopUpdatingLocation];
}



@end

我在网上查阅了一些资料,得知我应该使用MKPolyline并给它提供坐标。但我不确定如何存储这些地点并使用MKPolyline来连续绘制这些点,而且在应用程序运行时也需要持续更新。

1个回答

4
你只需要创建一个NSMutableArray来保存你在viewDidLoad中实例化的位置。所以,didUpdateToLocation(或者如果支持iOS 6及更高版本,则应使用didUpdateToLocations)仅需将位置添加到数组中,然后从该数组构建一个MKPolyline,将该MKPolyline添加到地图中,然后删除旧的MKPolyline。或者您可以将所有线段作为单独的MKPolyline对象添加,但是思路是相同的,创建一个模型来保存您的位置(例如NSMutableArray),然后将适当的MKPolyline对象添加到地图视图中。
例如,您可以这样做:
#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations lastObject];

    if (location.horizontalAccuracy < 0)
        return;

    [self.locations addObject:location];
    NSUInteger count = [self.locations count];

    if (count > 1) {
        CLLocationCoordinate2D coordinates[count];
        for (NSInteger i = 0; i < count; i++) {
            coordinates[i] = [(CLLocation *)self.locations[i] coordinate];
        }

        MKPolyline *oldPolyline = self.polyline;
        self.polyline = [MKPolyline polylineWithCoordinates:coordinates count:count];
        [self.mapView addOverlay:self.polyline];
        if (oldPolyline)
            [self.mapView removeOverlay:oldPolyline];
    }
}

记得指定地图如何绘制MKPolyline。将您的视图控制器设置为MKMapViewdelegate,然后您可以执行以下操作:

#pragma mark - MKMapViewDelegate

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
    if ([overlay isKindOfClass:[MKPolyline class]])
    {
        MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];

        renderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
        renderer.lineWidth   = 3;

        return renderer;
    }

    return nil;
}

// for iOS versions prior to 7; see `rendererForOverlay` for iOS7 and later

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
    if ([overlay isKindOfClass:[MKPolyline class]])
    {
        MKPolylineView *overlayView = [[MKPolylineView alloc] initWithPolyline:overlay];

        overlayView.strokeColor     = [[UIColor blueColor] colorWithAlphaComponent:0.7];
        overlayView.lineWidth       = 3;

        return overlayView;
    }

    return nil;
}

谢谢回复 :) 对不起,我还是新手!我已经实现了代码,但出现了一些错误,我相信这都是基础知识。我尝试将视图控制器设置为 MKMapView 的代理,使用 [mapView setDelegate:self]; 这样做对吗? - Khledon
@user3254994 是的,要指定MKMapView的委托,你可以在代码中这样做(或者你可以在IB中通过进入“连接检视器”来做)。关于self.locations的错误是因为你将其定义和/或实例化为NSArray而不是NSMutableArray。请使用后者。 - Rob
我已经运行了应用程序,但现在出现了这个错误 - 但代码中似乎没有任何错误 *** Terminating app due to uncaught exception 'NSUnknownKeyException',reason: '[<StartCycleViewController 0x125650d00> setValue:forUndefinedKey:]:此类不符合键值编码的要求,无法为键map设置值。' - Khledon
1
@user3254994 当你在Interface Builder(IB)中定义了不正确的插座时,通常会出现该错误。请检查“连接检查器”(即IB右侧面板中的最后一个选项卡)中的IBOutlet定义,并将其与代码中的IBOutlet定义进行比较。听起来像是在IB中存在一个到名为“map”的不存在属性的连接。 - Rob
1
@AceN - 是的,您必须在地图视图委托中实现mapview:rendererForOverlay:(或者在Swift中使用mapView(_:rendererFor:)),并且显然还要设置地图视图的delegate。如果没有这个方法,就不会渲染任何(可见的)覆盖层。 - Rob
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接