【问题标题】:Is it possible to distinguish between locking the device and sending an app to background?是否可以区分锁定设备和将应用程序发送到后台?
【发布时间】:2011-12-06 22:43:45
【问题描述】:

我有一个应用需要在使用 Home 按钮发送到后台时执行某些操作,而在使用顶部硬件按钮锁定设备时执行其他操作。解决这些需求的标准方法是UIApplication 发出的通知和委托方法。在 iOS 4 上,它们如下所示:

// Pressing the home button
Will resign active.
Did enter background.
// Tapping app icon on Springboard
Will enter foreground.
Did become active.

// Pressing the lock button
Will resign active.
// Unlocking the device
Did become active.

换句话说,很容易区分锁定和后台。在 iOS 5 上,行为发生了变化:

// Pressing the home button
Will resign active.
Did enter background.
// Tapping app icon on Springboard
Will enter foreground.
Did become active.

// Pressing the lock button
Will resign active.
Did enter background.
// Unlocking the device
Will enter foreground.
Did become active.

注意didEnterBackgroundwillEnterForeground 通知现在即使在(取消)锁定设备时也会发出,因此无法区分锁定和后台。此更改是否记录在某处?是回归吗?你知道区分这两种情况的另一种方法吗?

【问题讨论】:

标签: ios cocoa-touch


【解决方案1】:

iOS 6

在我通过模拟器进行的初步测试中,使用

检查应用程序状态
[[UIApplication sharedApplication] applicationState]

在任何一个

- (void)applicationWillEnterForeground:(UIApplication *)application

- (void)applicationDidEnterBackground:(UIApplication *)application

允许您区分呼叫锁定设备和切换回主屏幕。锁定屏幕将返回 1 (UIApplicationStateInactive),而按下主页按钮将注册为 2 (UIApplicationStateBackground)。

这似乎是一致的,应该可以在 iOS 设备上运行,就像在模拟器中一样可靠。

iOS 7

iOS 6 方法在 iOS 7 中不再有效。为了现在执行此操作,您必须使用 CFNotificationCenter 并监听 darwin 通知(标记为:com.apple.springboard.lockcomplete)。您可以在此处找到包含示例项目的 github 存储库:https://github.com/binarydev/ios-home-vs-lock-button

iOS 7 修复的功劳归于wqq

【讨论】:

  • 实际上,纯粹从这些方法的名称来看,您应该无法在willEnterForeground: 中确定在不同的情况下状态会返回1 还是2,并且在didEnterBackground: 中,状态应该始终是2。即使到下一个次要 iOS 版本,我也不会依赖这种行为保持不变。
  • 实际上,从 5.0 开始,无论您是锁定屏幕但不离开应用程序,还是通过主页按钮实际离开应用程序,都始终调用 didEnterBackground。我已经在 iPad 1 上进行了测试,并且两者都表现出相同的行为。这是因为当你锁屏时,它会调用didEnterBackground,但是UIApplicationStatus会是UIApplicationStateInactive,因为应用仍然在锁屏后的前台。以任何方式离开应用程序都会产生 UIApplicationStateBackground 。我认为这不会在近期的任何版本中发生变化。
  • 我可以确认这适用于 iOS 5 和 iOS 6 设备。谢谢!
  • @JoseRafaelSantiagoJr。嗨 Jose Rafael,我有同样的问题,但这不适用于 iOS 7。有没有办法在 iOS 7 中区分这两种状态。
  • @Archive 我已经确认这实际上在 iOS 7 中发生了变化。另一个 stackoverflow 用户找到了解决方案,我发布了一个 github 存储库,其中包含一个示例项目,展示了如何检测这个,这里:github.com/binarydev/ios-home-vs-lock-button
【解决方案2】:

我对此进行了相当多的研究,所以如果有人知道我不知道的事情,我很乐意在这里犯错,但从技术上讲,没有记录方法来区分锁定设备,并发送到后台。

但是,您可以检查的一件事是在从前景到背景的转换过程中的UIApplicationState。锁定设备将提供UIApplicationStateInactive,将应用程序移至后台将提供UIApplicationStateBackground。但是,由于这种行为没有正式记录,它可能会在未来发生变化。

一个基本的例子:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];
    NSLog(@"Device state: %@", state);
    switch (state) {
        case UIApplicationStateActive:
            /* ... */
            break;
        case UIApplicationStateInactive:
            /* Device was/is locked  */
            break;
        case UIApplicationStateBackground:
            /* User pressed home button or opened another App (from an alert/email/etc) */
            break;
    }
}

UIApplicationState - 应用程序的运行状态

typedef enum {
    UIApplicationStateActive,   
    UIApplicationStateInactive,
    UIApplicationStateBackground
}

UIApplicationState

常量

UIApplicationStateActive - 应用程序 正在前台运行,当前正在接收事件。可用的 在 iOS 4.0 及更高版本中。

UIApplicationStateInactive - 应用程序正在运行 前台但未接收事件。结果可能会发生这种情况 中断或因为应用程序正在转换到或 来自后台。

UIApplicationStateBackground - 应用程序是 在后台运行。


根据UIApplicationDelegate Protocol Reference

applicationWillResignActive:
didEnterBackground:
// ...
willEnterForeground:
applicationDidBecomeActive:

是在这两种情况下都被调用的唯一方法。


根据iOS 4.3 to iOS 5.0 API Diff,这些是关于UIApplicationUIApplicationDelegate 的唯一更改,所以我找不到他们记录这些通知更改的位置:

UIApplication.h
Added -[UIApplication setNewsstandIconImage:]
Added UIApplication.userInterfaceLayoutDirection
Added UIApplicationDelegate.window
Added UIApplication(UINewsstand)
Added UIApplicationLaunchOptionsNewsstandDownloadsKey
Added UIRemoteNotificationTypeNewsstandContentAvailability
Added UIUserInterfaceLayoutDirection
Added UIUserInterfaceLayoutDirectionLeftToRight
Added UIUserInterfaceLayoutDirectionRightToLeft

【讨论】:

  • 仅供参考 - 这种行为在 iOS 8 + Swift 中有所改变。在应用程序处于前台时锁定设备现在使用UIApplicationStateBackground
【解决方案3】:

这更像是一种解决方法/hack,但根据我的经验,它非常可靠。 当设备被屏幕锁定时(不仅仅是主页按钮,如果这是一个词:)) - 绑定网络(UDP)套接字被破坏。 我使用的是 GCDAsyncUDPSocket(之前也是 AsyncUDPSocket),当设备关闭时,它们都会可靠地触发网络/管道损坏错误。 在我的情况下,无论如何我都需要 UDP 套接字,对于其他应用程序可能有点臭,但是,如果您真的需要在这里区分,只需绑定/侦听 UDP 套接字而不进行任何操作并不会太糟糕。

这个笔记会[自毁];是 5 分钟(所以 Apple 不会发现)。

【讨论】:

    【解决方案4】:

    有一个thread about this issue on Apple Developer Forums(仅限注册开发者,抱歉)。要点是新行为是设计使然。有人要求使用新的 API 功能来区分这两个用例,但目前还没有任何效果。

    【讨论】:

      【解决方案5】:

      这是 Apple 的 iOS 编程指南所说的:

      按下睡眠/唤醒按钮是另一种中断类型 导致您的应用程序暂时停用。当用户按下 此按钮,系统禁用触摸事件,将应用程序移动到 背景,但设置应用程序的 applicationState 属性的值 到 UIApplicationStateInactive (而不是 UIApplicationStateBackground),最后锁屏。

      http://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

      因此,您应该检查applicationDidEnterBackground: 中的UIApplicationapplicationState 属性。如果是UIApplicationStateBackground,则用户按下了主页按钮。但如果是UIApplicationStateInactive,则用户锁定了设备。

      【讨论】:

      • FWIW,在我对 iOS 7 的测试中,这似乎不是真的。事实上,我从来没有在任何地方看到 UIApplicationStateInactive 的值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-30
      • 1970-01-01
      相关资源
      最近更新 更多