【问题标题】:HowTo initialise MKMapView with a given user location?如何使用给定的用户位置初始化 MKMapView?
【发布时间】:2010-11-29 02:00:05
【问题描述】:

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

编辑:

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

【问题讨论】:

    标签: iphone cocoa-touch mkmapview core-location


    【解决方案1】:

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

    = 在您的UIViewController 中维护两个独立的属性:一个到MKMapView,一个到CLLocationManager

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

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

    = 在 vi​​ewController 的 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 秒后更新。然后告诉位置管理器停止更新,让微调器停止动画,并获取纬度/经度数据并将其与视图跨度和区域一起分配给地图视图,以便它缩放并居中到正确的位置。

    = 现在是棘手的部分:蓝色大理石“颤抖”是 mapview 跟踪用户位置的一个特征。您将不得不暂时“伪造”它,直到真正的人开始出现(或者只是为当前位置使用单独的标记并自己保持其位置)。我个人会选择用户熟悉的蓝色大理石。

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

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

    = 让 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 的 userlocationlocation 属性具有值时调用它:

    -(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
    }
    

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

    = 在viewWillLoad 中,您可以将最后一个已知位置填充到自定义 bluemarble 注释中并显示它。打开/关闭 userLocation 跟踪,当您收到通知时,相同的 hide-the-annotation-show-the-real-marble 技巧将起作用。地图视图自己的位置管理器启动,当它有数据时,您可以让您的注释标记消失。

    = 您可能希望实现 viewController 的 viewWillDisappear 方法并手动关闭地图视图上的 userLocation 跟踪,以便在下次打开视图时默认关闭。您还需要获取最后一个已知的userLocation 并将其保存以备下次使用。这样,您可以在 viewWillAppear 方法中完成所有定位标记杂耍,而不必担心 userLocation 会干扰,直到您准备好。

    祝你好运。

    【讨论】:

    • 谢谢拉敏。这不是预期的解决方案,但我想它是最接近现有的解决方案。
    • 是的,如果他们允许我们将地图视图上的 userLocation 设置为初始值,那会容易得多……或者更好的是仍然允许使用现有的 CLLocationManager 实例而不是创建自己的实例。 ..但不幸的是他们没有。
    【解决方案2】:

    在您的控制器中:

    - (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];
    }
    

    当地图出现时,它将位于帕洛阿尔托附近

    【讨论】:

    • 这不是我需要的。我想更改蓝色位置指示器的位置(“当前位置”)。
    • userLocation 是只读属性,我怀疑你能做些什么。唯一合法的方法是禁用 Apple 提供的蓝色指示器并编写您自己的,这是毫无意义的
    • 设置一个 500m x 500m 的区域 [mapView setRegion:MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake(54.233498f, 1.99375f), 500, 500)];
    【解决方案3】:

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

    这是你想要的吗?

    【讨论】:

    • 不,这不是关于区域,而是关于位置指示器
    【解决方案4】:

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

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

    用户的位置是只读的,可以使用也可以不使用。这并不意味着您需要另一个位置经理来做您可能需要做的任何事情。听起来您的应用并不真正需要该功能,但我可能误解了您的问题。

    【讨论】:

    • 问题是没有显示用户位置,或者在前 10 秒显示错误,显示了新的 MKMapView。在这 10 秒之后,一切都很好。但是,据我所知,我很想跳过这 10 秒。
    • 可能有点旧,但如果有人读到这里,你应该在启动应用程序时获取用户位置,这将启动 GPS 来定位用户。这样,当用户打开地图时,他/她已经被定位。 pS:10秒很正常,打开定位后连谷歌地图都需要几秒
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 2013-10-27
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多