2

iOS 10 のローカル通知からのアクションでアプリの起動 (非アクティブ状態から) を実装しようとしています。

iOSで特定の時間にローカル通知を起動すると、ローカル通知に応答してアプリが正常に起動します。しかし、ここで必要なのは、通知内のデータに応じてアクションを実行することです。

iOS 8および9では、AppDelegateでセットアップしました

func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
    if (application.applicationState == UIApplicationState.inactive || application.applicationState == UIApplicationState.background) {
        NotificationCenter.default.post(name: Notification.Name(rawValue: "noteName", object: notification.alertBody)

ViewControllerでそれをキャッチするオブザーバー

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.txtFromNotifier), name: NSNotification.Name(rawValue: "noteName", object: nil)

iOS 10 では AppDelegate に追加されました:

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    // Determine the user action
    switch response.actionIdentifier {
    case UNNotificationDismissActionIdentifier:
        print("Dismiss Action")
    case UNNotificationDefaultActionIdentifier:
        print("Default")
        // do something here

UNNotification のデフォルト アクション (「デフォルト」は起動後にコンソールに出力されます) からパラメータを渡し、ViewController で txtFromNotifier 関数を実行する方法を見つけることができませんでした。NotificationCenter post / addObserver の組み合わせを使用しようとすると、アプリがバックグラウンドにある場合は機能しますが、アプリが非アクティブな場合は機能しません。

何か案は?

4

1 に答える 1

1

解決策を見つけました。通知ブロードキャストに遅延をラップしました。私の AppDelegate は次のようになります。didFinishLaunchingWithOptions で通知センターを選択する場合:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    if #available(iOS 10.0, *) {
        let center = UNUserNotificationCenter.current()
        center.delegate = self
        let options: UNAuthorizationOptions = [.alert, .badge, .sound]
        center.requestAuthorization(options: options) {
            (granted, error) in
            if !granted {
                print("Something went wrong")
            }
        }
    } else {
        application.registerUserNotificationSettings(UIUserNotificationSettings(types: [.alert , .badge , .sound], categories: nil))
    }
    return true
}

didReceiveNotification で、iOS 10 を選択します...

func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
    if #available(iOS 10.0, *) {
        // different notification centre for iOS 10, see @available below
    } else {
        if (application.applicationState == UIApplicationState.inactive || application.applicationState == UIApplicationState.background) {
            runAfterDelay(2.0) {  // 2 second delay, not sure if needed but doesn't seem to hurt - runAfterDelay function is below
                NotificationCenter.default.post(name: Notification.Name(rawValue: NSLocalizedString("ticker_notification_name", comment: "")), object: notification.alertBody)
            }
        } /*else {
         // handle the local notification when the app is open, if needed
         } */
    }
}

@available オプションを使用して、iOS 10 を選択します。

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    // Determine the user action
    switch response.actionIdentifier {
    case UNNotificationDismissActionIdentifier:
        print("Dismiss Action")
    case UNNotificationDefaultActionIdentifier:
        print("Default")
        runAfterDelay(3.0) {  // 3 second delay to give observer time to load. 3 seconds is arbitrary. runAfterDelay function is below
            NotificationCenter.default.post(name: Notification.Name(rawValue: NSLocalizedString("ticker_notification_name", comment: "")), object: response)  // .body
        }
    case "Snooze":
        print("Snooze")
    case "Delete":
        print("Delete")
    default:
        print("Unknown action")
    }
    completionHandler()
}

そして、オブザーバーに靴下を履く時間を与える runAfterDelay 関数:

func runAfterDelay(_ delay: Double, closure:@escaping ()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}

オブザーバーを変更する必要はなかったと思います-リビジョン履歴に変更はありません。元の質問の addObserver メソッドと同じように見えます。

于 2017-07-10T11:54:20.843 に答える