【问题标题】:Triggering a specific action when the app enters foreground from a local notification in iOS? (using swift)当应用程序从 iOS 中的本地通知进入前台时触发特定操作? (使用快速)
【发布时间】:2014-11-01 04:27:49
【问题描述】:

我正在使用新语言 Swift 构建一个 iOS 应用程序。现在它是一个 HTML5 应用程序,使用 UIWebView 显示 HTML 内容。该应用程序具有本地通知,我想要做的是当应用程序通过单击(触摸)本地通知进入前台时触发 UIWebView 中的特定 javascript 方法。

我看过这个question,但它似乎并没有解决我的问题。我也遇到过这个question,它告诉我有关使用 UIApplicationState 的信息,这很好,因为这可以帮助我知道应用程序从通知进入前台。但是当应用程序恢复时,我如何在应用程序恢复时显示的视图的 viewController 中调用方法?

我想做的是获取我的 ViewController 的一个实例并将其中的一个属性设置为 true。内容如下

class FirstViewController: UIViewController,UIWebViewDelegate { 
  var execute:Bool = false;
  @IBOutlet var tasksView: UIWebView!
}

在我的 AppDelegate 中我有方法

func applicationWillEnterForeground(application: UIApplication!) {
    let viewController = self.window!.rootViewController;
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

    var setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("FirstView") as FirstViewController
    setViewController.execute = true;


}

所以我想做的是当应用程序再次进入前台时,我想查看执行变量并运行如下方法,

if execute{
 tasksView.stringByEvaluatingJavaScriptFromString("document.getElementById('sample').click()");
}

我应该将用于从 webview 触发 javascript 的逻辑代码放在哪里?是在 viewDidLoad 方法上,还是在 webView 委托方法之一上?我试图将该代码放在 viewDidLoad 方法中,但布尔执行的值设置为其初始值,而不是应用程序进入前台时在委托中设置的值。

【问题讨论】:

标签: ios uiwebview swift uilocalnotification


【解决方案1】:

如果我希望在应用程序回到前台时通知视图控制器,我可能只注册UIApplication.willEnterForegroundNotification 通知(完全绕过应用程序委托方法):

class ViewController: UIViewController {

    private var observer: NSObjectProtocol?

    override func viewDidLoad() {
        super.viewDidLoad()

        observer = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [unowned self] notification in
            // do whatever you want when the app is brought back to the foreground
        }
    }

    deinit {
        if let observer = observer {
            NotificationCenter.default.removeObserver(observer)
        }
    }
}

注意,在完成闭包中,我包含[unowned self] 以避免强引用循环,如果您碰巧在块内引用self,则会阻止视图控制器被释放(如果您可能需要这样做)将更新一个类变量或做任何有趣的事情)。

还要注意,我删除了观察者,即使随便阅读 removeObserver documentation 可能会导致人们得出结论是不必要的:

如果您的应用面向 iOS 9.0 及更高版本或 macOS 10.11 及更高版本,则无需在其 dealloc 方法中取消注册观察者。

但是,当使用这种基于块的再现时,您确实需要删除通知中心观察者。正如the documentation for addObserver(forName:object:queue:using:) 所说:

要取消注册观察,请将此方法返回的对象传递给removeObserver(_:)。在释放addObserver(forName:object:queue:using:) 指定的任何对象之前,您必须调用removeObserver(_:)removeObserver(_:name:object:)

【讨论】:

  • 我很欣赏回复中的细节。现在您可能已经猜到了,我对 ios 编程非常陌生,并且没有在应用商店发布的经验。因此,如果我绕过应用程序委托方法进行通知,那会增加我的应用程序未清除应用商店提交审批流程的机会吗?
  • 不,这个通知是一个有文档的、完善的公共接口,所以它是被批准的机制。没关系。
  • 如果您注册了多个观察者,并且希望在 deinit 上删除所有观察者怎么办?
  • 注销每一个或执行:NSNotificationCenter.defaultCenter().removeObserver(self)
  • @rob 嗨,我遇到了一个奇怪的情况,当删除 avcapturesession 后,我的前台通知在进入后台后没有触发。 fg 通知起作用的唯一方法是,如果我在 bg 通知的任何位置放置一个断点。我尝试了您在上面添加的代码,当从 bg 到 fg 时没有任何寄存器。我从调试模式更改为发布模式并返回,但仍然没有。仅在 bg 通知代码中的任何位置放置断点时才有效
【解决方案2】:

我喜欢使用NotificationCenterPublisher 初始化器。使用它,您可以使用Combine 订阅任何NSNotification


import UIKit
import Combine

class MyFunkyViewController: UIViewController {

    /// The cancel bag containing all the subscriptions.
    private var cancelBag: Set<AnyCancellable> = []

    override func viewDidLoad() {
        super.viewDidLoad()
        addSubscribers()
    }

    /// Adds all the subscribers.
    private func addSubscribers() {
        NotificationCenter
            .Publisher(center: .default,
                       name: UIApplication.willEnterForegroundNotification)
            .sink { [weak self] _ in
                self?.doSomething()
            }
            .store(in: &cancelBag)
    }

    /// Called when entering foreground.
    private func doSomething() {
        print("Hello foreground!")
    }
}

【讨论】:

    【解决方案3】:

    在 ViewController 中添加以下代码

    override func viewDidLoad() {
    super.viewDidLoad()
    let notificationCenter = NotificationCenter.default
    notificationCenter.addObserver(self, selector:#selector(appMovedToForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
       }
    
      @objc func appMovedToForeground() {
      print("App moved to foreground!")
      }
    

    【讨论】:

    • 观察者是否需要在某个时候被移除?
    • 是的,当 viewController deinit 时移除观察者是一个好习惯。如果您添加了任何 NotificationCenter,请添加类似 deinit { NotificationCenter.default.removeObserver(self) } 的内容。
    • 引自上面 - 如果您的应用程序针对 iOS 9.0 及更高版本或 macOS 10.11 及更高版本,则无需在其 dealloc 方法中取消注册观察者。
    【解决方案4】:

    在 Swift 3 中,它替换并生成以下内容。

        override func viewDidLoad() {
            super.viewDidLoad()
    
            foregroundNotification = NotificationCenter.default.addObserver(forName: 
            NSNotification.Name.UIApplicationWillEnterForeground, object: nil, queue: OperationQueue.main) {
               [unowned self] notification in
    
            // do whatever you want when the app is brought back to the foreground
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      相关资源
      最近更新 更多