请告诉我如何在后台开始 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()
}
答案 0 :(得分:0)
几乎可以肯定你所要求的是不可能的,而且有充分的理由。每两分钟下载一个小资源的应用基本上几乎不断地保持蜂窝无线电。即使在最好的情况下,这也是一个巨大的电池耗尽 - 几乎与持续打电话一样糟糕。
在理论中,您可以使用backgroundTaskWithExpirationHandler让您在两分钟后执行某些操作,并在上一个请求完成或失败后两分钟启动新请求。
在练习中,如果您的应用经常在后台唤醒并启动新请求,则NSURLSession机制会故意引入唤醒应用的延迟。经过一段时间后,我会比每两分钟运行的频率低得多,我相信,虽然我没有看过NSURLSession部分的代码,所以我无法确定你是否会超过它的阈值。
无论哪种方式,这都是一个非常糟糕的主意。在后台获取偶尔的数据是背景提取的目的,如果你提出的请求比背景提取更频繁,那就意味着你正在做一些你不应该做的事情,这是一个好方法让您的应用被拒绝。
如果您真的需要以近乎实时的方式了解应用程序外部的内容,那就是推送通知的目的。