iOS 应用程序在后台时的通知

iOS Notification when App is in Background

我想知道是否可以在 iOS 中启动后台进程。在我的后台进程中,每 30 分钟应该调用一个函数,以便检查我的数据库是否有新消息等,以便发送通知。我不想实施推送通知。 我不知道在哪里实现此功能,以及是否有覆盖功能,例如在 AppDelegate 中。

感谢您的帮助, 汉内斯

您想要的是 "Background Fetch",从 iOS 7:

开始可用

https://www.objc.io/issues/5-ios7/multitasking/

是的,可以在 iOS 中启动后台进程。也可以每 30 分钟启动一次此过程。你需要设置两件事!您需要每 30 分钟向您的服务器发送一次静默推送。(例如,在 Parse 中使用 Cloud Code 作业(警告!由于 Parse 将于 2017 年 1 月关闭,因此在此平台上工作并不聪明)

此静默推送会启动一个 NSURLBackgroundSession,它会从您的服务器中提取所需的数据并进行处理。

Your need to activate this in the project settings

1.) 在 AppDelgate 中添加这个用于接收推送

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
    application.registerForRemoteNotifications()
}

当您从服务器或其他设备收到推送时,将调用以下委托方法:(因此也将其添加到您的 appDelegate 中)

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)
     {
        NSLog("Silent Push recevied")
        let vc = ViewController()
        vc.pullData() // call your pullData method...
     }

现在调用的方法需要从您的数据库中提取数据。在这种情况下,您使用 NSURLSession 来下载您需要的任何内容。

2.) 转到处理数据的 ViewController 并添加: 具有所需委托方法的 NSURLSessionDownloadDelegate 委托

class vc : ViewController, NSURLSessionDownloadDelegate{
func viewDidLoad()
{
super.viewDidLoad()
}

func pullData()
{
let url = NSURL(string: "http://example.com")!
let urlRequest = NSURLRequest(URL: url, cachePolicy: .UseProtocolCachePolicy, timeoutInterval: 5)
let backgroundSessionConfiguration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("backgroundSessionIDX")
backgroundSession = NSURLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let task = backgroundSession.downloadTaskWithRequest(urlRequest)
            task.resume()
}
}

当下载任务成功完成时

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL)
{
}

将被调用,您可以处理数据

let path = location.path
let data = NSFileManager.defaultManager().contentsAtPath(path!)

您也可以使用 NSURLSessionDataTask

我建议你看看Apple's documentation on Background Execution. It states all the possible ways to run code in the background. Each method comes with it's limitations, advantages and disadvantages and also Apple mentions:

In iOS, only specific app types are allowed to run in the background

如果您的 iOS 应用程序不通过蓝牙(BTLE 或 MFi 认证设备)与某些设备通信(您可以将该蓝牙设备配置为每 30 次向 iOS 设备发送一些事件分钟并在发生这种情况时执行您的代码),那么每 30 分钟 运行 一些代码的最可靠方法是使用静默推送通知。
静默推送通知可以配置为不向用户显示,但允许您的代码 运行。推送通知的局限性在于,用户需要有效的互联网连接才能接收它们,并且用户需要授予您的应用使用推送通知的权限(您可以在应用的第一个请求 运行)。
我注意到您的问题提到了 我不想使用推送通知,但不幸的是您在这里真的别无选择。

背景

在你的 viewDidLoad() 方法中

 let notificationCenter = NotificationCenter.default
 notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)

将此方法添加到您的 ViewController

 @objc func appMovedToBackground() {
   print("App moved to background!")
 }

对于地面

  override func viewDidLoad() {
    super.viewDidLoad()


    let notificationCenter = NotificationCenter.default
    notificationCenter.addObserver(self, selector: #selector(appMovedToForground), name: UIApplication.willEnterForegroundNotification, object: nil)

 }

@objc func appMovedToForground() {
   print("App moved to forground!")
}