如何使用给定的用户位置初始化MKMapView?

时间:2009-09-17 08:50:25

标签: iphone cocoa-touch mkmapview core-location

我的应用知道当前用户位置(CoreLocation.framework)。 一旦用户打开新的MapView,他的iPhone就会再次开始搜索当前位置。 是否可以跳过它或更改mkMapView的第一个用户位置?

编辑:

是否可以覆盖MKMapView并使用其他LocationManager?

4 个答案:

答案 0 :(得分:42)

是的,可以有一个单独的位置管理器对象,并将其值分配给mapview(顺便说一下,我在下面使用'='作为列表前缀,以防止SO代码格式化程序被borking)。

=在UIViewController维护两个单独的属性中:一个属于MKMapView,另一个属于CLLocationManager

=使用MKMapView和您想要的任何其他窗口镶边创建一个XIB文件。将插座连接到控制器属性。确保MKMapView不会关注用户位置。

=让UIViewController实现CLLocationManagerDelegate协议 - 尤其是locationManager:didUpdateToLocation:fromLocation:方法,只要有新的位置值,就会调用该方法。我们将控制器设置为位置管理器的委托。

=在viewController的loadView方法中,加载带有MKMapView的NIB。要向用户提供反馈,您可能需要设置UIActivityIndicatorView微调器并将其设置为startAnimating。然后你开始:

self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
self.locationManager.distanceFilter = 10; // or whatever
[self.locationManager startUpdatingLocation];

=在locationManager:didUpdateToLocation:fromLocation:中检查自上次N秒后事件是否更新。然后告诉位置管理器停止更新,微调器停止动画,获取纬度/经度数据并将其与视图范围和区域一起分配到地图视图,以便缩放并居中到正确的位置。

=现在这里是棘手的部分:蓝色大理石'throbber'是mapview跟踪用户位置的一个功能。你必须暂时“假装”它,直到真正的人开始(或者只是为当前位置使用单独的标记并自己保持其位置)。就个人而言,我会选择用户熟悉的蓝色大理石。

=为了使其在启动时显示,您需要创建一个自定义MKAnnotationView,只需在位置管理器返回的位置添加蓝色大理石图形。这意味着拍摄一个Mapview的快照,其中显示的位置,然后将蓝色大理石用于拍摄,并将其用作自定义注释视图的图像。

=如果您希望它主动跟踪地图,您可以启用mapview的用户位置跟踪,当它获取实际数据时,您隐藏先前设置的标记并让mapview进行更新。另一种选择是允许现有的位置管理器每隔一秒左右继续接收更新,并自行更新蓝色大理石注释的位置。

=让mapview自己的userLocation执行更新添加到viewDidLoad:

[self.map.userLocation addObserver:self 
forKeyPath:@"location" 
options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) 
context:NULL];
self.map.showsUserLocation = YES; // starts updating user location

=实施observeValueForKeyPath。当mapview的location的{​​{1}}属性具有值时,它会被调用:

userlocation

=为了避免显示当前位置的预热延迟,请保持对包含地图和位置管理器的viewController的引用,这样它就不会消失(这有点像内存耗尽但是如果你释放了它将不得不再次等待,直到MapView加载了瓷砖并准备好了。

=在-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([self.map isUserLocationVisible]) { [self.locationManager stopUpdatingLocation]; self.ownBlueMarble.hidden = YES; } // The current location is in self.map.userLocation.coordinate } 中,您可以将最后一个已知位置填入自定义bluemarble注释并显示它。打开/关闭userLocation跟踪,当你收到通知时,同样的hide-the-annotation-show-the-real-marble技巧将起作用。 mapview自己的位置管理器启动,当它有数据时,你可以让你的注释标记消失。

=您可能希望实现viewController的viewWillLoad方法,并在mapview上手动关闭viewWillDisappear跟踪,以便在下次启动视图时默认关闭。您还需要获取最后一个userLocation并将其保存以供下次使用。这样,您可以使用userLocation方法执行所有定位标记 - 玩杂耍,并且在您准备好之前不必担心用户位置干扰。

祝你好运。

答案 1 :(得分:27)

在您的控制器中:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    CLLocationCoordinate2D coord = {latitude: 37.423617, longitude: -122.220154};
    MKCoordinateSpan span = {latitudeDelta: 1, longitudeDelta: 1};
    MKCoordinateRegion region = {coord, span};
    [mapView setRegion:region];
}

当地图出现时,它将居中靠近Palo Alto

答案 2 :(得分:0)

尝试在初始化时将showUserLocation属性设置为false,然后恢复之前的region地图视图(显然必须在销毁之前的地图之前存储它)。

这是你想要的吗?

答案 3 :(得分:0)

您不需要使用其他位置管理器,您可以将您想要的任何点添加到地图中,并通过您想要的任何其他逻辑更新它们。

假设您有一个与遥控车的套接字连接,并且该车发回包含有效负载中的地理位置信息的套接字数据。您可以解析它,并实时更新地图上缩略图的位置。不需要“userLocation”属性,但如果您愿意,可以显示它。

用户的位置是只读的,您可以使用或不使用。这并不意味着您需要其他位置经理来执行您可能需要执行的任何操作。听起来你的应用程序并不真正需要这个功能,但我可能会误解你的问题。