在 Swift 中的应用程序中的任何地方运行一个函数 N 次

Posted

技术标签:

【中文标题】在 Swift 中的应用程序中的任何地方运行一个函数 N 次【英文标题】:Run a function N time anywhere in the app in Swift 【发布时间】:2017-08-12 18:54:09 【问题描述】:

我试图为我的项目制作一个调用应用程序,并且我想添加一个函数来不断检查是否有人调用。我的应用使用 Firebase,我有一个密钥供每个用户检查他是否拨打了电话。

我在这里面临两个问题,第一个问题是,正如我所说,我希望我的函数不断检查应用程序中的任何位置是否有来电。另一个问题是我有一个视图控制器,当有人打电话时我想弹出它。我在 github 上找到了这段代码,但它使用了我没有在我的应用程序中使用的导航控制器:

extension UIViewController
func presentViewControllerFromVisibleViewController(viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) 
    if let navigationController = self as? UINavigationController, let topViewController = navigationController.topViewController 
        topViewController.presentViewControllerFromVisibleViewController(viewControllerToPresent: viewControllerToPresent, animated: true, completion: completion)
     else if (presentedViewController != nil) 
        presentedViewController!.presentViewControllerFromVisibleViewController(viewControllerToPresent: viewControllerToPresent, animated: true, completion: completion)
     else 
        present(viewControllerToPresent, animated: true, completion: completion)
    


【问题讨论】:

你在使用 CallKit 吗? @ryantxr 不,我正在使用 api 嗨,亚历克斯。我们不希望帖子以 完美 英语为特色,但如果您可以使它们尽可能地具有可读性,那么这里的读者将非常感激。看起来你的帖子都是小写的——注意句子应该以大写开头,当提到你自己时,“I”也应该大写。如果您可以在以后的帖子中进行这些更改,那就太好了! 【参考方案1】:

有关监控何时出现来电并因此被呼叫的问题,请参阅answer。这可能是您需要的(但是我从未尝试过)。该示例显示了创建 CXCallObserver 并将您的 AppDelegate 设置为委托。

对于您的第二个问题,我首先尝试this answer,它利用了 window.rootViewController,因此您可以从您的 AppDelegate 执行此操作。一般来说,当你尝试为你的 AppDelegate 做 UI 时,根 VC 是你的朋友。 :)

基于 Alex 添加的 cmets 的更好答案:

我先看看如何为您的 Firebase 模型设置一个观察者,以便您获得回调。如果您没有办法做到这一点,我会在 Firebase 模型属性上使用 KVO。但是要完全按照您的要求进行操作,并从 AppDelegate(而不是单例)懒惰地这样做,请参阅以下代码:

// In AppDelegate

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

    self.timerToCheckForCalls = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)


func timerFired()

    let didCall = // TODO: query your Firebase model...
    guard didCall == true else
    
        return
    

    self.displayCallerView()


func displayCallerView()

    // See below link.

请参阅this answer 了解如何展示您的视图控制器,即使您的应用程序可能正在显示操作表、警报等...我认为您尤其重视这一点,因为您需要显示调用者无论什么您的应用正在运行。

请注意,当用户滚动 UITextView 时,计时器不会触发。在其他情况下,计时器也可能会延迟。因此,最好是观察您的 Firebase 模型或接收 KVO 回调,而不是使用计时器。

【讨论】:

感谢您的回答,但我没有使用 CallKit 我正在使用 api 您需要帮助来使用您的调用 API 调整类似策略吗?如果是这样,您使用的是什么 API? 我正在使用 twilio,但我还不会使用它,我只需要该函数检查一个名为“calling”的键,其值在 firebase 数据库中设置为 false并在整个应用程序中执行此操作,因此基本上该函数将在应用程序的任何位置重复调用,当有人拨打电话时,密钥将更改为 true,并且会弹出一个带有呼叫者姓名的视图,并且当用户只接受时然后 api 将完成它的工作并连接两个用户。希望你能明白【参考方案2】:

如果您想创建一个可以从任何地方调用的函数,请使用单例模式。您也可以使用它来存储您的特殊视图控制器。

请记住,此代码不应视为功能齐全的代码,需要您自定义以满足您的需求。

class MyClass 
    let shared = MyClass()
    var viewController: SpecialViewController?
    func checkForCall() 
        // do function stuff
    

    func getSpecialViewController() 
        let storyBoard = UIStoryboard.init(name: "main", bundle: nil)
        // keep it so we don't have to instantiate it every time
        if viewController == nil 
            viewController = storyBoard.instantiateViewController(withIdentifier: "SomeViewController")
        
        return viewController
    



// Make an extension for UIViewController so that they can all
// use this function
extension UIViewController 
    func presentSpecialViewController() 
        let vc = MyClass.shared.getSpecialViewController()
        present(vc, animated: false, completion: nil)
    

代码中的某处:

// in some function
MyClass.shared.checkForCall()

代码中的其他地方:

presentSpecialViewController()

【讨论】:

以上是关于在 Swift 中的应用程序中的任何地方运行一个函数 N 次的主要内容,如果未能解决你的问题,请参考以下文章

如何从android studio中的任何地方访问localhost数据库

Swift中的函数调用

Swift 中的下拉搜索栏/视图?

在 swift 中,如何在应用程序委托中实现一个变量,以便在应用程序的任何地方检索它?

Swift函数式编程十三(函子适用函子单子)

Swift函数式编程十三(函子适用函子单子)