Xcode / iOS模拟器:手动触发重大位置更改

77

有没有一种方式可以手动告诉设备触发一个显著位置变化通知,以唤醒所有注册了该通知的应用程序? 这仅用于测试,我意识到此私有API调用将在提交到应用商店时被拒绝。


2
我深入研究了私有框架头文件,但没有找到任何类似于触发此问题的东西。只能通过携带笔记本电脑上车并四处开车来测试这个问题并不方便。 - Nick
2
如果您使用CLLocationManager的didUpdateToLocation:fromLocation:委托,则可以使用startUpdatingLocation而不是startMonitoringSignificantLocationChanges进行测试。如果在CLLocationManager中未设置过滤器,则在具有中等良好的GPS接收情况下,它几乎每秒钟调用一次didUpdateToLocation。对于测试目的,这可能会有所帮助。 - thomas
1
这并不是测试CLLocationManager输出的问题,而是应用程序在通过重大位置更改“唤醒”时的生命周期问题。 - Nick
如果您拥有Apple Dev账户,您可能想要查看iOS5 UIAutomation。它可能最终为您提供解决方案。唯一的障碍是我不知道是否可以通过UIAutomation将程序置于后台模式。 - Barney Mattox
就此而言,Xcode不允许您的应用程序被正确地挂起(https://forums.developer.apple.com/thread/14855),这可能会导致意外结果。在正常设备上,它实际上会被挂起,但由于您正在通过Xcode运行,它只会保持在后台以进行调试... - mfaani
10个回答

195

所以有两个答案:

A) 上火车 :-)

B) 使用模拟器。在iOS 5.x 模拟器中,有一个调试菜单,其中包含位置子菜单。选择高速公路驾驶。这将在北加利福尼亚州风景优美的280号公路上开始模拟器的想象之旅。它为您提供了除了视图以外的一切:您的应用程序将获得重大位置更改更新 ,如果它已被暂停,还将在后台启动

为了验证您是否实际移动,请在模拟器中启动 Safari,转到 maps.google.com 并单击小的跟踪我的位置按钮。您应该在移动。

太棒了!现在如何调试被系统启动的生命周期问题?简单!让 xCode 等待您的应用程序启动以开始调试。从方案菜单中选择编辑方案。在运行方案和信息选项卡中,对于“启动”设置,选择:“等待 My.app 启动”。

在模拟器中运行您的应用程序一次,以便开始监视位置更新,然后强制退出它,以使其挂起。在应用程序完成启动函数中添加一个断点,然后等待。只要您的模拟器足够远,您的应用程序将被唤醒,触发您的断点,您就可以获得想要的。

但实际上,坐火车更有趣。


2
有人在iOS 6.X模拟器上尝试过吗?我无法让它工作。 - Segev
2
我也无法在iOS 6.1模拟器和XCode 4.6上运行成功。 - Stephen Petschulat
1
等待时间太长,请参考 @Chris 的解决方案。 - DanSkeel
3
iOS9.3 + xCode 7.3 更新:这种方法非常有效!(注意: 确保正确处理 requestAlwaysAuthorization() + 适当的 info.plst 键)。另外,设置 distanceFilter = 500 让我每隔30-40秒 (有时甚至是 ~15秒) 收到位置更新 ;) - Vexy
1
五年过去了,这还能在XCode 9上运行吗?我已经按照上面的步骤做了一切。等了大约5分钟,什么也没有发生。 - Dibzmania
显示剩余8条评论

18

我发现可以通过打开和关闭飞行模式和/或WiFi来实现这一点。也许可以在设备处于飞行模式下启动应用程序,然后关闭应用程序并关闭飞行模式。这将打开GPS并强制分派位置更新。


1
这对我来说行不通,无法重新启动一个使用重大位置变化监测的已终止应用程序。 - aslı
1
是的!这是一个非常好的想法!我的问题是当设备被锁定时如何让系统启动我的应用程序,而这个“飞行模式”解决方案在iOS 9上运行得非常好!非常感谢! - nverinaud

4

我还想测试我已终止的应用程序的重新启动,该应用程序使用了重要更改监视。我编写了一段代码,以便在启动选项字典中使用位置密钥启动时显示本地通知。

我在模拟器中运行了我的应用程序。然后从多任务栏中将其关闭。然后我将iOS模拟器的位置设置为自定义位置。我退出模拟器并重新启动它。我的应用程序接收到了重要的位置更新并显示了本地通知。


3
我曾经遇到同样的问题,如何测试“startMonitoringSignificantLocationChanges”并检查我的应用程序在挂起时是否接收到位置更新。我无法通过断点捕获执行,但我成功地通过将新位置数据发送到服务器来查看我的实现工作的结果。
整个流程如下: - 使用“startMonitoringSignificantLocationChanges”和API调用来更新位置纬度和经度 - 将位置更新后台模式功能设置为true - 运行应用程序,以便启动位置管理器并监听位置更改 - 强制关闭应用程序 - 在模拟器上将调试->位置设置为高速公路驾驶 - 打开地图以查看位置是否正在更改 - 等待服务器更新位置,并每约3分钟获取新结果
然而,我仍然不确定这在真实设备上是否足够好。我使用的是Xcode版本6.0.1(6A317),在模拟器iPhone 5s(8.0)上进行了测试。

3

除了MagicSeth的答案,如果您需要在真实设备上测试而不是模拟器上,您可以通过在设置应用程序中的隐私屏幕中禁用并重新启用位置服务,并使用UIApplication.LaunchOptionsKey.location密钥触发后台启动。


这将比答案更好的评论。 - Jodast
我无法通过模拟器找到解决方案,但在iOS 12上运行得非常好。 - duncanc4

1
根据您的情况,我建议两种解决方案:
  1. 使用定时器或本地通知,定期调用stopMonitoringSignificantLocationChanges,然后再调用startMonitoringSignificantLocationChanges,这应该会触发将新位置发送到您的代码(可能与之前相同的位置)。

  2. 构建自己的GPS模拟器,在调试版本中启动,并调用与CLLocationManager相同的委托方法。


这里涉及到一个应用程序生命周期的本质问题。 - Nick
这里涉及到应用程序的生命周期,这是问题的核心。当应用程序被终止并通过重大位置更改进入后台时,它将被启动。我们需要测试应用程序在后台启动后的行为,包括寿命和网络通信。我们通过实际花一天时间驾车在城市中监控控制台记录活动来解决了我们的问题。 - Nick

1
我注意到在iOS 7和Xcode 5.1.1中,如果您期望SLC事件将您的应用程序启动到后台模式,则可能会或可能不会触发您设置的断点。 对于我来说,有时甚至不会显示NSLog消息。
如果您也遇到了这种情况,您可以从系统日志中查看NSLog输出。您可以从iOS模拟器的Debug菜单中打开系统日志。

0
在iOS 4中,您可以注册以获取重要位置更改的服务。根据苹果文档:通过此服务,仅在用户的位置发生重大变化时生成位置更新;因此,它非常适合社交应用程序或提供用户非关键位置相关信息的应用程序。如果应用程序在更新发生时被挂起,则系统会在后台唤醒它来处理更新。如果应用程序启动此服务,然后终止,系统将在有新位置可用时自动重新启动应用程序。该服务仅适用于带有蜂窝电台的设备上,且只适用于iOS 4及更高版本。
请查看此处的苹果文档这里
以下是一些示例代码,可用于注册以获取重要位置更新:
- (void)startSignificantChangeUpdates {

// Create the location manager if it doesn't exist
if (nil == locationManager)
    locationManager = [[CLLocationManager alloc] init];

locationManager.delegate = self;
[locationManager startMonitoringSignificantLocationChanges];

}

文档中提到:如果您让此服务保持运行状态,而您的应用程序随后被挂起或终止,该服务会在新位置数据到达时自动唤醒您的应用程序。在唤醒时,您的应用程序被放置在后台,并被分配一小段时间来处理位置数据。由于您的应用程序在后台运行,因此它应该尽量减少工作量,并避免任何可能导致其在分配的时间到期之前无法返回的任务(例如查询网络)。如果没有这样做,您的应用程序可能会被终止。

谢谢...我明白它的工作原理,并且已经使用了一段时间。问题是如何在不开车触发设备的情况下进行测试 - Nick
啊,抱歉。我可以删除我的回答吗? - Jane Sales

-1

高速公路驾驶

enter image description here

// MARK: - MKMapViewDelegate

  func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
    guard let location = userLocation.location else { return }

    print(location.speed)
  }

-4

嗯,这是不可能的,因为应用程序范围仅限于其自己的空间,这种类型的通知不能使用苹果文档化的API列表生成。 当然...如果使用了任何未经记录的API,应用程序将因使用未记录/私有API而被苹果拒绝。


显然...在回答之前请先阅读问题。"这只是用于测试,我意识到这个私有API调用将在提交到应用商店时被拒绝。" - Nick

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