Swift 中的后台处理

Background Processing in Swift

I Switched to push notifications, check my answer below.

我正在尝试实现一个 运行 在应用程序置于后台时在后台执行的功能。该实现类似于一个计时器,当我们退出应用程序时,该计时器必须保持 运行ning。我已经在我的应用程序中激活了 "Background Processing",这是我想要在后台 运行 的功能:

 public func keepCheck(timer:Timer) {
        DispatchQueue.global(qos: DispatchQoS.background.qosClass).async {
            print("do some background task")
            if self.check == true {
                if self.outBool == false {
                    self.residualWaterWeight -= self.indoorDryRate
                    if self.residualWaterWeight <= 0.0 {
                        self.appDelegate?.scheduleNotification(notificationType: "Your Clothes are Dry!",body: "I Love fabric conditioner smell in the morning <3")
                        self.defaults.set(false, forKey: "keep_check")
                    }
                    print(self.residualWaterWeight)
                } else {
                    self.do10min()
                }
                self.check = self.defaults.bool(forKey: "keep_check")

            }

            DispatchQueue.main.async {
                print("update some UI")
            }
        }
    }

现在,此功能 运行 在应用程序打开时在后台运行,但在您点击主页按钮时停止。如何防止此功能在应用暂停时停止?

尽管被否决了,但我仍然认为我的解决方案可能对 iOS 开发中的通知新手有用。我从本地通知切换到推送通知,设置我的远程烧瓶应用程序来处理所有后台处理和使用 firebase 发送的通知:

  1. 按照本教程设置您的应用以接收推送通知:https://www.youtube.com/watch?v=34kvGKdPN2k

  2. 在您的远程服务器上创建一个 Flask 应用程序并部署它。如果您没有远程服务器,我使用了来自 https://www.digitalocean.com . then you can follow exactly the instructions here to create and deploy your flask application: https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-uswgi-and-nginx-on-ubuntu-18-04 的 5 欧元/月 ubuntu 服务器(这些说明适用于任何 ubuntu 服务器,并且他们还有针对不同 OS).

  3. 将 flask 配置为服务器:https://firebase.google.com/docs/admin/setup

DISCLAIMER: you should't proceed if you haven't follow successfully the previous steps.

  1. 现在,如果您是 Flask 的新手,它会非常巧妙地处理 HTTP 请求,而且非常直观。

    4.1。打开你的烧瓶应用程序进行编辑 nano myproject.pyvim myproject.py

    4.2 在您的导入中添加 import requestsfrom pyfcm import FCMNotification,并在导入之后添加:push_service = FCMNotification(api_key=SERVER_KEY) 其中 SERVER_KEY 是项目设置中来自 firebase 的服务器密钥。

    4.3 添加以下代码(所有大写代码中的每一位都可以更改):

@app.route('/MY_REQUEST_NAME')
def MY_FUNCTION():
    # MY_ARGUMENT in this case will be the iOS device token
    MY_ARGUMENT = str(request.args.get('MY_ARGUMENT'))
    # do calculations
    result = push_service.notify_single_device(registration_id=MY_ARGUMENT, message_title=MESSAGE, message_body=BODY)
    return MY_RESULTS
    # if you're goal is just sending notification you don't really need a return statement

4.4 保存并退出,然后在您的服务器中激活您的虚拟环境 source myprojectenv/bin/activate 并输入 pip install requests pyfcm

当您在浏览器中输入时,Flask 应用程序将触发我们刚刚编写的函数:http://your_domain.com/my_request_name?my_argument=my_argument_value 或者您可以使用您的服务器 public IP 地址而不是域,如果您没有.

  1. 如果您没有 SSL 证书(您使用的是 http 而不是 https),则必须返回 Xcode 并在您的Info.plist:

  1. 转到您的 AppDelegate 并修改以下函数以将设备 fcm_token 存储在某处。我个人使用了 defaults.standard:
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
      print("Firebase registration token: \(fcmToken)")

      // Save Token:
      UserDefaults.standard.set(fcmToken, forKey: "FCM_TOKEN")

      NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
      // TODO: If necessary send token to application server.
      // Note: This callback is fired at each app startup and whenever a new token is generated.
    }
  1. 最后,在 Xcode 中,您可以这样调用 http 请求:
let token = UserDefaults.standard.string(forKey: "FCM_TOKEN")!
        let url : URL = URL(string: "http://your_domain.com/my_request_name?my_argument=\(token)")!
        let task = URLSession.shared.dataTask(with: url)
        task.resume()