0

The answer provided by Rean Wen in this post worked great in Swift 2.2, but now I upgraded to XCode 8.0 with Swift 3 and it does not work anymore.

I am getting the following error message:

.../project/AppDelegate.swift:41:108: Cannot convert value of type '(@convention(c) (CFNotificationCenter?, UnsafeMutableRawPointer?, CFString?, UnsafeRawPointer?, CFDictionary?) -> Void)!' to expected argument type 'CFNotificationCallback!'

from this line:

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), nil, LockNotifierCallback.notifierProc(), "com.apple.springboard.lockcomplete", nil, CFNotificationSuspensionBehavior.DeliverImmediately)

inside the AppDelegate.swift file.

Does anyone know how to solve this issue? Since I just started learning Swift, any help will be greatly appreciated.

Community
  • 1
  • 1
Paul S
  • 3
  • 3

2 Answers2

0

This may work for you.

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                    nil,
                                    { (_, observer, name, _, _) in

                                        print("received notification: \(name)")
        },
                                    "com.apple.springboard.lockcomplete" as CFString!,
                                    nil,
                                    .deliverImmediately)

You can check this answer for more detail.

Community
  • 1
  • 1
technerd
  • 14,144
  • 10
  • 61
  • 92
-1

I encountered the same problem when I was developing a task management app recently. I try to solve this problem using Darwin Notification with CFNotificationCallback method.

Step 1:

Add the following code right under AppDelegate class declaration

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    let displayStatusChanged: CFNotificationCallback = { center, observer, name, object, info in
        let str = name!.rawValue as CFString
        if (str == "com.apple.springboard.lockcomplete" as CFString) {
            let isDisplayStatusLocked = UserDefaults.standard
            isDisplayStatusLocked.set(true, forKey: "isDisplayStatusLocked")
            isDisplayStatusLocked.synchronize()
        }
    }

    //other functions
}
Step 2:

Inside didFinishLaunchingWithOptions, add the following code:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:
[UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    let isDisplayStatusLocked = UserDefaults.standard
    isDisplayStatusLocked.set(false, forKey: "isDisplayStatusLocked")
    isDisplayStatusLocked.synchronize()

    // Darwin Notification
    let cfstr = "com.apple.springboard.lockcomplete" as CFString
    let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
    let function = displayStatusChanged
    CFNotificationCenterAddObserver(notificationCenter,
                                    nil,
                                    function,
                                    cfstr,
                                    nil,
                                    .deliverImmediately)

    return true
}
Step 3:

Inside applicationDidEnterBackground, add the following code:

func applicationDidEnterBackground(_ application: UIApplication) {      
    let isDisplayStatusLocked = UserDefaults.standard
    if let lock = isDisplayStatusLocked.value(forKey: "isDisplayStatusLocked"){
        // user locked screen
        if(lock as! Bool){            
            // do anything you want here
            print("Lock button pressed.")
        }
        // user pressed home button
        else{            
            // do anything you want here
            print("Home button pressed.")
        }
    }
}
Step 4:

Inside applicationWillEnterForeground, add the following code:

func applicationWillEnterForeground(_ application: UIApplication) {
    print("Back to foreground.")
    //restore lock screen setting
    let isDisplayStatusLocked = UserDefaults.standard
    isDisplayStatusLocked.set(false, forKey: "isDisplayStatusLocked")
    isDisplayStatusLocked.synchronize()  
}

You can take a look at the detailed approach here with a demo project: swift-home-vs-lock-button

Eric Hu
  • 3
  • 3