为什么self.locationManager stopUpdatingLocation不能停止位置更新

26
问题:似乎我无法阻止Core Location向我的应用程序发送更新/跟踪。

我的做法:在我的 viewDidAppear 中,我调用self.locationManager并将其传递给一个方法以在地图上显示用户的位置(MKMapView的一个实例)。getter 被覆盖以检查服务是否可用,以查看其是否被授权。如果是,它会allocs/inits并startMonitoringSignificantLocationChanges然后返回。
在viewDidDisappear中,我调用[self.locationManager stopUpdatingLocation]。但是,我仍然可以在状态栏中看到位置图标。即使我通过双击主页按钮并关闭它来终止应用程序,图标仍然存在...即使经过长时间(10分钟以上)。当我打开“设置”应用时,它告诉我我的应用仍在使用位置服务(紫色图标)。
问题:我错过了什么?为什么位置更新不停止?
谢谢。

如果你有两个问题(即使它们是相关的),你应该分别提出两个问题。 - benzado
没关系,问题的第二部分我已经删除了。我找到了答案。谢谢。 - Sierra Alpha
Swift版本 - Juan Boero
9个回答

16

startMonitoringSignificantLocationChanges的反义词不是stopUpdatingLocation,而是stopMonitoringSignificantLocationChanges

除非您有特定原因只监测重要位置变化,否则您可能希望将startMonitoringSignificantLocationChanges替换为startUpdatingLocation以获得更加规律的更新。

请查看CLLocation文档获取更多详细信息。


我两种都试过。事实上,当我第一次编写代码时,它是stopMonitoringSignificantLocationChanges,但由于它没有停止更新,所以我将其更改为stopUpdatingLocation。我正在尝试在地图上显示某种类型的商业场所的位置,因此我只需要用户的位置一次。我不需要跟踪它。 - Sierra Alpha
2
对于你的情况,我仍然建议使用startUpdatingLocation方法,并在你的CLLocationManagerDelegate中调用stopUpdatingLocation方法,一旦你获取到了足够准确的位置信息。 - jnic
2
我看到这个答案被标记为正确。jnic的回答是有效的,但我怀疑我下面提供的回答才是正确的。 - Christopher
我的应用程序似乎仍然在无限跟踪,即使我已经调用了[stopUpdatingLocation]...从苹果文档中看来,该调用实际上是“允许”CLLocationManager停止跟踪,如果它想要的话,例如,如果没有其他类正在监听它。我的应用程序只需要获得一个良好的初始定位,然后我想在整个过程中关闭位置服务...但我似乎无法实现这一点。我根本不使用地图视图。 - Reid
在 viewDidDisappear 方法中,[self.locationManager stopUpdatingHeading];self.locationManager = nil; 对我起了作用。 - EarlySun

13

我也曾经遇到了和Canopus相同的问题。即使调用了stopUpdatingLocation,如果启用了showUserLocation,导航指针仍会留在状态栏上。也许这是一个bug?可能是因为我正在运行和测试iOS 4.2.1,并且这个问题可能已经在后来的SDK中得到了修复。

我认为如果调用了stopUserLocation,它也应该停止显示用户位置,因为我使用它的视图已经消失并随后被释放。

似乎你必须在停止用户位置更新之前将showUserLocation设置为NO。

无论如何,在我的viewDidLoad方法中,我有以下代码:

self.mapView.showsUserLocation = YES;

更多的代码...

- (void)viewWillDisappear:(BOOL)animated
{    
    if (locationManager)
    {
        mapView.showsUserLocation = NO;
        [locationManager stopUpdatingLocation];
    }

    [super viewWillDisappear:animated];
}

- (void)dealloc
{
    if (locationManager)
    {
        [locationManager release];
        locationManager = nil;
    }

    (other code)
}

7
这是因为stopUpdatingLocation只是告诉LocationManager你不再需要位置更新了,但mapView有它自己的locationManager仍在请求位置更新,同时启用showsUserLocation。只有当没有任何东西等待位置更新时,GPS硬件才会关闭,因此指示器会保持开启状态。 - aranasaurus
对我也起作用。您可以在调试导航器/能源影响中看到,位置服务已关闭。该图标将显示GPS的使用时间更长几秒钟。 - Gondomir

5

Swift:

你的地图和位置管理器都需要停止:

override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        locationManager.stopMonitoringSignificantLocationChanges()            
        locationManager.stopUpdatingLocation()
        mapView.showsUserLocation = false

    }

您可以在Xcode中的调试导航器下的能源影响中调试/检查位置服务使用情况。


为了我的目的,当应用程序进入后台(监听通知.UIApplicationDidEnterBackground)时,我也关闭了showsUserLocation,并在获取.UIApplicationDidBecomeActive并显示视图(if self.isViewLoaded && (self.view.window != nil))时再次打开它。在我的情况下,使用GPS的地图视图与应用程序在前台和后台使用位置管理器进行其他目的是独立的。在设备上,位置“箭头”显示大约10秒后关闭。 - James

2
我在委托后将locationManager属性设置为nil,解决了这个问题。
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    // Your code getting coordinates 
    //Here set nil
    locationManager = nil;

}

当我尝试将其值设置为nil时,无法将locationManager设置为nil,我收到了类型不匹配错误。 - crazy_phage
请展示更多关于locationManager的代码,它是一个变量吗?在文档中哪里说我们应该将manager设置为nil? - Juan Boero

1

我在Swift中使用CLLocationManager,这与Swift或Objective-C相关,但我只是创建了一个布尔值,每当我收到位置更新时,我就将其更新为true。由于在我的情况下,我只需要在启动时使用它一次.. 例如,

// my boolean to stop location updates
var alreadyUpdatedLocation = Bool()

此外,在我的情况下,我创建了一个帮助函数,每当我获取用户的数据/位置时,我只需像这样调用自己的stopUpdatingLocation

// helper function to stop updates
func stopUpdationgLocation() {

    // since I received my data within a block, I don't want to just return whenever it wants to :)    
    dispatch_async(dispatch_get_main_queue()) {

        // the building stop updating location function call
        self.locationManager.stopUpdatingLocation()

        // my own trick to avoid keep getting updates
        self.alreadyUpdatedLocation = true

    }
}

然后,无论您在何处使用接收到的位置更新,您都可以这样做...
// avoiding multiple calls after I have received user location
if(self.alreadyUpdatedLocation) {
        return
}

我希望它有所帮助!


保留循环问题在前方。 - Juan Boero

1
我的应用程序请求“始终”授权,只有应用程序内的某个特定功能需要该授权。如果用户关闭了该功能,则在应用程序关闭时我们可以停止位置更新(以节省电池并从状态栏中删除位置图标)。我也认为停止不起作用,因为在应用程序关闭后,状态栏中的位置图标仍然存在,即使我的应用程序是唯一具有位置访问权限的正在运行的应用程序,并且在应用程序关闭时我告诉它停止更新位置。对我来说,解决方案是要更加耐心,然后我意识到 iOS 大约需要 10-15 秒钟才能关闭位置硬件并更新状态栏。我不必将我的位置管理器设置为 nil 或进行任何特殊处理,只需在应用程序关闭时停止更新,等待 15 秒钟,然后观察 iOS 从状态栏中删除位置图标。希望这能帮助某些人!

0

试试这个...

    if ([CLLocationManager significantLocationChangeMonitoringAvailable])
            {
                [self.locationManager startMonitoringSignificantLocationChanges];


            }

 [[self locationManager] stopUpdatingLocation];

0
问题: 我的情况下,我同时使用了startMonitoringSignificantLocationChanges和startUpdatingLocation。即使通过locationManager.stopMonitoringSignificantLocationChanges()和locationManager.stopUpdatingLocation()停止了位置,我的位置仍然不断被调用。
解决方案: 1. 检查是否已经使计时器失效。 2. 初始化locationManager.delegate = nil。
这些方法肯定会解决你的问题。

0
如果您正在使用GoogleMaps SDK for iOS,我发现如果您调用

,则可能会导致应用程序崩溃。
locationManager.stopUpdatingLocation() 

仍然有

mapView.isMyLocationEnabled = true

然后GPS图标保持不变。

我选择的做法是在地图上最初显示用户位置,然后在8秒后关闭它。使用GoogleMaps SDK,这对我起作用。我在ViewDidLoad中添加了以下内容:

DispatchQueue.main.asyncAfter(deadline: .now() + 8.0, execute: {
            self.locationManager.stopUpdatingLocation()
            self.mapView.isMyLocationEnabled = false
        }) 

如果你希望在切换到另一个视图时不在状态栏中显示GPS图标,那么你可以将相同的代码放在viewWillDisappear中。


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