如何在iOS中开始后台URLSession?

时间:2016-10-12 21:22:36

标签: ios swift background push nsurlsession

请告诉我如何在后台开始 URLSession。我只找到了如何完成和处理结果的方法。接下来是逻辑:静默推送通知命令对Web服务器执行一些请求并获取一些json,之后执行其他任务。 不要建议后台获取,因为我需要每隔几分钟刷新一次数据。

修改

所以,实际上我的应用只打印连接的startMonitoring已连接,而不是其他内容。我希望最终收到收到的JSON

很抱歉没有提供我的代码。这是:

AppDelegate.swift:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    let aps = userInfo["aps"] as! [String: AnyObject]
    print("connected")
    // 1
    if (aps["content-available"] as? NSString)?.integerValue == 1 {
        var MLController = ((window?.rootViewController as? UITabBarController)?.viewControllers?.first as? UINavigationController)?.viewControllers.first as? MonitoringListTableViewController
        MLController?.startMonitoring()
        //completionHandler(UIBackgroundFetchResult.noData)
        print("connected")
    }
}

MonitoringListTableViewController.swift

    func startMonitoring() {

        print("startMonitoring")
        self.connect()
        //tokenTimer.invalidate()
        //tokenTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(tokenReloader), userInfo: nil, repeats: true)

    }

    func connect() {

        //Gets encrypted token

        for theCookie in HTTPCookieStorage.shared.cookies! {
            HTTPCookieStorage.shared.deleteCookie(theCookie)
        }
        let request = NSMutableURLRequest(url: URL(string: "http://...")!)

        let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            guard error == nil && data != nil else {           // check for fundamental networking error
                print("error=\(error)")
                return
            }
            if let httpStatus = response as? HTTPURLResponse , httpStatus.statusCode != 200 {           // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(response)")
            }

            let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            //print("responseString = \(response), \(responseString)")
            for theCookie in HTTPCookieStorage.shared.cookies! {
                if(theCookie.name.hasPrefix("x1")) { self.UUU.x1= theCookie.value }
                if(theCookie.name.hasPrefix("x2")) { self.UUU.x2= theCookie.value }


            print("SUCCESS")
            self.tokenReloader()
        })
        task.resume()

    }

func tokenReloader() {


            let context: JSContext? = {
                let context = JSContext()

                // 1
                guard let
                    commonJSPath = Bundle.main.path(forResource: "x3", ofType: "js") else {
                        print("Unable to read resource files.")
                        return nil
                }

                // 2
                do {
                    let common = try String(contentsOfFile: commonJSPath, encoding: String.Encoding.utf8)
                    _ = context?.evaluateScript(common)
                } catch (let error) {
                    print("Error while processing script file: \(error)")
                }

                return context
            }()

            let parseFunction = context!.objectForKeyedSubscript("x3")
            let parsed = parseFunction?.call(withArguments: [UUU.encryptedToken!]).toString()


            requestT(withTokensOf: UUU)

    //}

     //   else { attempts = attempts + 1 }

    }

func requestT(withTokensOf theUUU : UUUClass) {

        let _UUU = theUUU
        for (index, theWatching) in watchingList.enumerated() {

            _UUU.dictToProps(dict: theWatching.propsToDict())

            self.makeRequest("**some_post_request**", url: "...", num: index, _UUU: _UUU)

        }

    }

    func makeRequest(_ parameters: String, url:String, num: Int, _UUU: UUUClass){
    let uuu = _UUU
    let postData:Data = parameters.data(using: String.Encoding.utf8)!
    //let postLength:NSString = String(postData.length)
    let request = NSMutableURLRequest(url: URL(string: url)!)
    let session = URLSession.shared
    request.httpMethod = "POST"
    request.httpBody = postData

    //request.setValue("text/html,application/xhtml+xml,application/xml;q=0.9,*;q=0.8", forHTTPHeaderField: "Accept")
    request.setValue("*/*", forHTTPHeaderField: "Accept")

    //print(request.allHTTPHeaderFields)

    let task = session.dataTask(with: request as URLRequest, completionHandler: {
        (data1, response, error) -> Void in
        guard error == nil && data1 != nil else {
            let _error = error as? NSError
            let themessage : String

            print("error=\(_error?.code)")
            return
        }

        let httpResponse = response as! HTTPURLResponse
        let statusCode = httpResponse.statusCode
        print(statusCode)
        if (statusCode == 200) {
            print("Everyone is fine, data received successfully.")
            print("response: \(response); data: \(data1)")

            let json = JSON(data: data1!)
            if (json["error"].boolValue == true) { return }
            print("JSON received: \(json.description)")

        }
        else {
            print("Error - no response")
             }
    })

    task.resume()
}

1 个答案:

答案 0 :(得分:0)

几乎可以肯定你所要求的是不可能的,而且有充分的理由。每两分钟下载一个小资源的应用基本上几乎不断地保持蜂窝无线电。即使在最好的情况下,这也是一个巨大的电池耗尽 - 几乎与持续打电话一样糟糕。

理论中,您可以使用backgroundTaskWithExpirationHandler让您在两分钟后执行某些操作,并在上一个请求完成或失败后两分钟启动新请求。

练习中,如果您的应用经常在后台唤醒并启动新请求,则NSURLSession机制会故意引入唤醒应用的延迟。经过一段时间后,我会比每两分钟运行的频率低得多,我相信,虽然我没有看过NSURLSession部分的代码,所以我无法确定你是否会超过它的阈值。

无论哪种方式,这都是一个非常糟糕的主意。在后台获取偶尔的数据是背景提取的目的,如果你提出的请求比背景提取更频繁,那就意味着你正在做一些你不应该做的事情,这是一个好方法让您的应用被拒绝。

如果您真的需要以近乎实时的方式了解应用程序外部的内容,那就是推送通知的目的。