【问题标题】:detect screen unlock events in IOS Swift在 IOS Swift 中检测屏幕解锁事件
【发布时间】:2017-02-07 10:09:09
【问题描述】:

如何检测 iPhone 上的屏幕解锁事件?当用户解锁它时,我想在我的应用程序中执行一个操作。我在谷歌上搜索但只找到与目标 C 相关的代码,将其更改为 swift 但它不起作用。
关注这个博客: http://kidtechblogs.blogspot.com/2014/07/how-to-detect-screen-lockunlock-events.html.
任何帮助我如何快速检测到它。 下面是改成swift的代码..

func displayStatusChanged(center: CFNotificationCenter, observer: Void, name: CFString, object: Void, userInfo: CFDictionaryRef) {
        // the "com.apple.springboard.lockcomplete" notification will always come after the "com.apple.springboard.lockstate" notification
        let lockState = (name as String)
        print("Darwin notification NAME = \(name)")
        if (lockState == "com.apple.springboard.lockcomplete") {
            print("DEVICE LOCKED")
        }
        else {
            print("LOCK STATUS CHANGED")
        }
    }

func registerforDeviceLockNotification() {
        //Screen lock notifications
        CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),     //center
                nil,     // observer
                displayStatusChanged,     // callback
                CFSTR("com.apple.springboard.lockcomplete"),     // event name
                nil,     // object
                .deliverImmediately)
        CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),     //center
                nil,     // observer
                displayStatusChanged,     // callback
                CFSTR("com.apple.springboard.lockstate"),     // event name
                nil,     // object
                .deliverImmediately)
    }

【问题讨论】:

  • 当应用程序在前台时,darwin 通知是否有效?
  • 此代码无效。
  • 首先,您的方法 displayStatusChanged 假设是静态的。请检查一下。

标签: ios swift


【解决方案1】:

我刚刚更新了代码

只需将 registerforDeviceLockNotification() 函数调用到应用委托 didfinishLunch 函数(AppDelegate.swift)中

如果您正在使用会话,则将 registerforDeviceLockNotification() 函数调用到 willConnectTo (SceneDelegate.swift)

示例代码(AppDelegate.swift)

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        registerforDeviceLockNotification()
        return true
    }
    
    func registerforDeviceLockNotification() {
        //Screen lock notifications
        CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),     //center
            Unmanaged.passUnretained(self).toOpaque(),     // observer
            displayStatusChangedCallback,     // callback
            "com.apple.springboard.lockcomplete" as CFString,     // event name
            nil,     // object
            .deliverImmediately)

    }
    
    private let displayStatusChangedCallback: CFNotificationCallback = { _, cfObserver, cfName, _, _ in
        guard let lockState = cfName?.rawValue as String? else {return}

        if (lockState == "com.apple.springboard.lockcomplete") {
               print("DEVICE LOCKED")
           } else {
               print("LOCK STATUS CHANGED")
           }

       
    }

示例代码(SceneDelegate.swift)

func registerforDeviceLockNotification() {
    //Screen lock notifications
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),     //center
        Unmanaged.passUnretained(self).toOpaque(),     // observer
        displayStatusChangedCallback,     // callback
        "com.apple.springboard.lockcomplete" as CFString,     // event name
        nil,     // object
        .deliverImmediately)

}

private let displayStatusChangedCallback: CFNotificationCallback = { _, cfObserver, cfName, _, _ in
    guard let lockState = cfName?.rawValue as String? else {return}

    if (lockState == "com.apple.springboard.lockcomplete") {
           print("DEVICE LOCKED")
       } else {
           print("LOCK STATUS CHANGED")
       }

   
}




 

【讨论】:

  • 我使用了你的代码,这是可行的......但我的应用程序被拒绝,苹果永远不会接受访问“com.apple.springboard.lockcomplete”。有什么想法吗?
【解决方案2】:

您的代码示例中有一些错误:

  • 在 swift 中使用 CFString 是通过一个简单的转换完成的:myString as CFString,不再是 CFSTR()...
  • 获取通知回调的最简单方法是使用Unmanaged.passUnretained(self).toOpaque() 添加观察者。这将使您有可能在课堂上捕获回调

最后,swift 版本与 Objective-c 版本完全不同,这里是 Swift 3 中的完整代码:

func registerforDeviceLockNotification() {
    //Screen lock notifications
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),     //center
        Unmanaged.passUnretained(self).toOpaque(),     // observer
        displayStatusChangedCallback,     // callback
        "com.apple.springboard.lockcomplete" as CFString,     // event name
        nil,     // object
        .deliverImmediately)
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),     //center
        Unmanaged.passUnretained(self).toOpaque(),     // observer
        displayStatusChangedCallback,     // callback
        "com.apple.springboard.lockstate" as CFString,    // event name
        nil,     // object
        .deliverImmediately)
}

private let displayStatusChangedCallback: CFNotificationCallback = { _, cfObserver, cfName, _, _ in
    guard let lockState = cfName?.rawValue as? String else {
        return
    }

    let catcher = Unmanaged<MyClassObserving>.fromOpaque(UnsafeRawPointer(OpaquePointer(cfObserver)!)).takeUnretainedValue()
    catcher.displayStatusChanged(lockState)
}

private func displayStatusChanged(_ lockState: String) {
    // the "com.apple.springboard.lockcomplete" notification will always come after the "com.apple.springboard.lockstate" notification
    print("Darwin notification NAME = \(lockState)")
    if (lockState == "com.apple.springboard.lockcomplete") {
        print("DEVICE LOCKED")
    } else {
        print("LOCK STATUS CHANGED")
    }
}

为了以防万一,别忘了移除你的观察者:

CFNotificationCenterRemoveObserver(CFNotificationCenterGetLocalCenter(),
                                   Unmanaged.passUnretained(self).toOpaque(),
                                   nil,
                                   nil)

【讨论】:

  • 这对我有用,但是当我解锁 iPhone 时,我收到两次“设备解锁”消息。设备锁定的状态是否比“锁定”和“解锁”更多?
  • @NikitaSavchuk 如果您收到两次“DEVICE UNLOCKED”,您能否解决双重消息问题?
  • @Tomasero 很遗憾,但没有
  • let catcher = Unmanaged.fromOpaque(UnsafeRawPointer(OpaquePointer(cfObserver)!)).takeUnretainedValue() MyClassObserving 的这一行出现错误。你能告诉我这是什么吗??
  • @HakikatSingh 我也是这样,你是怎么解决的?
【解决方案3】:

据我们所知,您无法使用本机代码检测屏幕锁定解锁状态。通过使用私有 api 将有机会检测屏幕锁定解锁状态。如果您使用的是苹果的私有 api,您的应用可能会被拒绝。我们建议不要使用苹果私有 api。

如果您想在越狱设备中进行屏幕锁定解锁事件,您可以从下面的链接中找到答案

Getting state for system wide notifications in iOS and OS X

Lock Unlock events iphone

Detect screen on/off from iOS service

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2018-11-18
    • 2017-03-02
    • 2018-05-08
    相关资源
    最近更新 更多