"hyperlocal" 应用程序获取用户位置(也处于终止状态)的适当方法
Appropriate way to get user's location(also in killed state) for an "hyperlocal" app
要求 - 我正在构建一个超本地化应用程序,它将根据用户的位置向其提供报价。在应用程序中时,我可以获得他的当前位置并相应地显示优惠,但我现在需要的是根据他的位置向用户发送推送通知。所以我想找出用户的位置并根据他的位置发送报价。
我已阅读 Apple 文档,因为 Significant-Change Location Service but then this answer 说一旦应用程序被终止,它就无法工作。
我也读过有关 Tracking the User’s Location 的内容,但这对我来说并不适用。我在后台收到的更新不超过 5 个。
我当前的代码在 viewDidLoad
-
if (self.locationManager == nil)
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
self.locationManager.allowsBackgroundLocationUpdates = true;
self.locationManager.pausesLocationUpdatesAutomatically = false;
if ([CLLocationManager authorizationStatus] != AVAuthorizationStatusAuthorized) {
[self.locationManager requestAlwaysAuthorization];
}
}
[self.locationManager startUpdatingLocation];
我的委托方法如下所示 -
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
if (UIApplication.sharedApplication.applicationState == UIApplicationStateActive) {
// Get updated data according to location
} else {
// Send location to server
}
}
我的应用功能和我的 plist -
请建议一些合适的方法,我可以在 1 公里左右的精度上生活。
另一种方法-
我可以在 "Background Mode- Background Fetch" 的 fetchNewDataWithCompletionHandler:
中获取用户的位置吗?
我可以使用静默推送通知的 application:didReceiveRemoteNotification:fetchCompletionHandler:
获取用户的位置吗? ): 根据
不可能
您好,只需创建一个 UILocalNotification
并使用您的详细信息进行设置,最重要的是在您输入 Region
时触发通知 添加 region
属性 请参阅 docs
希望对您有所帮助
所以,你的问题基本上是 "How can I get around Apple's specifically designed user interaction for people wanting to make my app shut up?"
答案是 "Not if you want to stay within the rules for the AppStore".
听着,如果用户决定终止您的应用程序(即他们将其向上滑动并退出任务管理器),此设计的全部意义在于 您的应用程序停止执行任何操作。 Apple 设计这个是为了让人们可以快速关闭您似乎想要实现的那种行为。我不太明白你为什么要规避它。我同意这种交互可能有点晦涩(毕竟,用户也可以 allow/disallow 应用程序在“设置”应用程序的后台接收位置更新的权利),但这就是交互 iOS 定义的.
如果我没理解错的话,你已经成功地正确设置了后台定位模式,所以即使你的应用程序不在前台(即在后台或暂停,在后一种情况下)也可以接收位置更新iOS 短暂唤醒它,以便您可以处理位置更新,例如发送本地通知以通知用户)。这已经很好了。
哦,不要害怕设备重启。是的,重启后你的应用程序在技术上不是 运行,但由于用户上次没有明确杀死它,iOS 将它视为处于挂起模式,IIRC,所以你仍然会获得重要的位置更新,并能做出正确的反应。
(以更一般的方式:人们通常似乎认为实际的应用程序进程状态反映了应用程序状态,因为它在文档 and/or 中定义,应用程序是否显示在任务管理器中与之相关。两者都不是完全正确。)
编辑 在你评论后特别询问我关于后台获取的问题:
抱歉,这可能并不完全清楚。我没有具体回答这个子问题,因为在 用户 有意退出您的应用程序后,您不应该按照他们的意图 "cheat" 进行解释。静默推送通知不会因此而起作用,是的。
我不知道 background fetch 是否会以类似的方式被抑制(可能是,但我没试过),但我认为不会'对你也没有帮助,即使它还在工作(我怀疑,Apple 可能会在这方面很努力)。我也从未尝试过(重新)启动此方法中的位置更新,所以我不能说这是否有效(一旦调用完成处理程序,系统可能至少会再次暂停您的应用程序,我不确定这个 "resets" "user killed the app flag" 系统似乎使用它来决定唤醒哪个应用程序并将位置更新传递到)。
application:performFetchWithCompletionHandler:
(因为它被完全调用)将被 OS 基于启发式调用,它试图成为 "clever"。由于该方法旨在从不提供推送通知的后端获取一些数据,因此调用它的次数可能会受到严格限制,如 documentation 中所述。决定何时调用 OS 的实际机制是一个黑匣子,试图欺骗它在需要时被调用是一场赌博。这很可能在数小时后发生。想想以下场景:
- 您的应用程序在后台定位模式下运行良好(我的理解是正确的,因为您已成功设置?请参阅 here and here)
- 用户手动终止了您的应用。为了这个论点,我们假设这不会阻止系统稍后重新启动它以给它一个后台获取机会
- 由于其他应用程序 运行 在系统上并且用户目前只有边缘连接,OS 决定现在不是启动后台获取的时候(我只是假设在这里,这些因素发挥了作用,正如所说它是一个黑盒子,但这些对我来说似乎是合理的)。您的用户绕过了一些您可能感兴趣的位置。
- 两个小时后,用户此时位于完全不同的区域,您的应用程序由 OS 再次启动并收到
application:performFetchWithCompletionHandler:
调用。您再次开始位置更新(让我们假设甚至可以工作并且系统不会立即再次终止应用程序,即即使在虚假后台获取之后它也会在后台提供位置更新)。您错过了几个位置,但该应用程序现在可以处理新位置。你所有的逻辑基本上都搞砸了,因为你没有计划丢失这么多位置更新...
- (可选:一段时间后,您的用户意识到您的应用显然在做某事,即使他们终止了它(例如,他们注意到电池耗尽)。他们将删除您的应用并留下一次性评论... )
- (可选 2,最坏情况:一旦苹果意识到可以在用户以这种方式杀死应用程序后重新启动后台位置更新,他们只需关闭 iOS 更新中的漏洞你的应用又回到了我们开始的地方...)
郑重声明:我不是在捍卫 Apple 做出的任何设计决定,我知道这会让你头晕目眩,就像一个人可以代表 "preserve battery and user intent under all circumstances" 一个人可以代表一个人一样更好的背景跟踪。我只是指出他们在这里处于控制之中,并且试图绕过他们在平台上设置的任何特定交互范例可能不是一个好主意。
综上所述,恐怕 "user terminated the app, now I won't get any location updates" 只是您必须忍受的东西。为什么这对你来说甚至是一个问题,考虑到你没有说背景定位模式对你来说不够用?我能想象的唯一(有问题的)场景是一种跟踪器应用程序,可能会在分发给送货服务员工或其他东西的设备上提供。如果是这样(并且抛开这些东西背后的道德规范,请注意,在某些国家甚至这样做是非法的......),我不得不说 iOS 根本不是正确的平台。
要求 - 我正在构建一个超本地化应用程序,它将根据用户的位置向其提供报价。在应用程序中时,我可以获得他的当前位置并相应地显示优惠,但我现在需要的是根据他的位置向用户发送推送通知。所以我想找出用户的位置并根据他的位置发送报价。
我已阅读 Apple 文档,因为 Significant-Change Location Service but then this answer 说一旦应用程序被终止,它就无法工作。
我也读过有关 Tracking the User’s Location 的内容,但这对我来说并不适用。我在后台收到的更新不超过 5 个。
我当前的代码在 viewDidLoad
-
if (self.locationManager == nil)
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
self.locationManager.allowsBackgroundLocationUpdates = true;
self.locationManager.pausesLocationUpdatesAutomatically = false;
if ([CLLocationManager authorizationStatus] != AVAuthorizationStatusAuthorized) {
[self.locationManager requestAlwaysAuthorization];
}
}
[self.locationManager startUpdatingLocation];
我的委托方法如下所示 -
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
if (UIApplication.sharedApplication.applicationState == UIApplicationStateActive) {
// Get updated data according to location
} else {
// Send location to server
}
}
我的应用功能和我的 plist -
请建议一些合适的方法,我可以在 1 公里左右的精度上生活。
另一种方法-
我可以在 "Background Mode- Background Fetch" 的
fetchNewDataWithCompletionHandler:
中获取用户的位置吗?我可以使用静默推送通知的
application:didReceiveRemoteNotification:fetchCompletionHandler:
获取用户的位置吗? ): 根据 不可能
您好,只需创建一个 UILocalNotification
并使用您的详细信息进行设置,最重要的是在您输入 Region
时触发通知 添加 region
属性 请参阅 docs
希望对您有所帮助
所以,你的问题基本上是 "How can I get around Apple's specifically designed user interaction for people wanting to make my app shut up?" 答案是 "Not if you want to stay within the rules for the AppStore".
听着,如果用户决定终止您的应用程序(即他们将其向上滑动并退出任务管理器),此设计的全部意义在于 您的应用程序停止执行任何操作。 Apple 设计这个是为了让人们可以快速关闭您似乎想要实现的那种行为。我不太明白你为什么要规避它。我同意这种交互可能有点晦涩(毕竟,用户也可以 allow/disallow 应用程序在“设置”应用程序的后台接收位置更新的权利),但这就是交互 iOS 定义的.
如果我没理解错的话,你已经成功地正确设置了后台定位模式,所以即使你的应用程序不在前台(即在后台或暂停,在后一种情况下)也可以接收位置更新iOS 短暂唤醒它,以便您可以处理位置更新,例如发送本地通知以通知用户)。这已经很好了。
哦,不要害怕设备重启。是的,重启后你的应用程序在技术上不是 运行,但由于用户上次没有明确杀死它,iOS 将它视为处于挂起模式,IIRC,所以你仍然会获得重要的位置更新,并能做出正确的反应。 (以更一般的方式:人们通常似乎认为实际的应用程序进程状态反映了应用程序状态,因为它在文档 and/or 中定义,应用程序是否显示在任务管理器中与之相关。两者都不是完全正确。)
编辑 在你评论后特别询问我关于后台获取的问题:
抱歉,这可能并不完全清楚。我没有具体回答这个子问题,因为在 用户 有意退出您的应用程序后,您不应该按照他们的意图 "cheat" 进行解释。静默推送通知不会因此而起作用,是的。
我不知道 background fetch 是否会以类似的方式被抑制(可能是,但我没试过),但我认为不会'对你也没有帮助,即使它还在工作(我怀疑,Apple 可能会在这方面很努力)。我也从未尝试过(重新)启动此方法中的位置更新,所以我不能说这是否有效(一旦调用完成处理程序,系统可能至少会再次暂停您的应用程序,我不确定这个 "resets" "user killed the app flag" 系统似乎使用它来决定唤醒哪个应用程序并将位置更新传递到)。
application:performFetchWithCompletionHandler:
(因为它被完全调用)将被 OS 基于启发式调用,它试图成为 "clever"。由于该方法旨在从不提供推送通知的后端获取一些数据,因此调用它的次数可能会受到严格限制,如 documentation 中所述。决定何时调用 OS 的实际机制是一个黑匣子,试图欺骗它在需要时被调用是一场赌博。这很可能在数小时后发生。想想以下场景:
- 您的应用程序在后台定位模式下运行良好(我的理解是正确的,因为您已成功设置?请参阅 here and here)
- 用户手动终止了您的应用。为了这个论点,我们假设这不会阻止系统稍后重新启动它以给它一个后台获取机会
- 由于其他应用程序 运行 在系统上并且用户目前只有边缘连接,OS 决定现在不是启动后台获取的时候(我只是假设在这里,这些因素发挥了作用,正如所说它是一个黑盒子,但这些对我来说似乎是合理的)。您的用户绕过了一些您可能感兴趣的位置。
- 两个小时后,用户此时位于完全不同的区域,您的应用程序由 OS 再次启动并收到
application:performFetchWithCompletionHandler:
调用。您再次开始位置更新(让我们假设甚至可以工作并且系统不会立即再次终止应用程序,即即使在虚假后台获取之后它也会在后台提供位置更新)。您错过了几个位置,但该应用程序现在可以处理新位置。你所有的逻辑基本上都搞砸了,因为你没有计划丢失这么多位置更新... - (可选:一段时间后,您的用户意识到您的应用显然在做某事,即使他们终止了它(例如,他们注意到电池耗尽)。他们将删除您的应用并留下一次性评论... )
- (可选 2,最坏情况:一旦苹果意识到可以在用户以这种方式杀死应用程序后重新启动后台位置更新,他们只需关闭 iOS 更新中的漏洞你的应用又回到了我们开始的地方...)
郑重声明:我不是在捍卫 Apple 做出的任何设计决定,我知道这会让你头晕目眩,就像一个人可以代表 "preserve battery and user intent under all circumstances" 一个人可以代表一个人一样更好的背景跟踪。我只是指出他们在这里处于控制之中,并且试图绕过他们在平台上设置的任何特定交互范例可能不是一个好主意。
综上所述,恐怕 "user terminated the app, now I won't get any location updates" 只是您必须忍受的东西。为什么这对你来说甚至是一个问题,考虑到你没有说背景定位模式对你来说不够用?我能想象的唯一(有问题的)场景是一种跟踪器应用程序,可能会在分发给送货服务员工或其他东西的设备上提供。如果是这样(并且抛开这些东西背后的道德规范,请注意,在某些国家甚至这样做是非法的......),我不得不说 iOS 根本不是正确的平台。