后台抓取将不会运行

时间:2019-01-22 21:39:42

标签: ios swift

我正在尝试创建一个应用程序,该应用程序会定期自动登录到网站,并在相关数据已更改的情况下向他们发送本地通知。

我正在使用后台抓取来实现此目的,并且当我模拟后台抓取时,效果很好。但是,它似乎从未在物理设备上单独运行

我尝试过: *将应用程序放在手机上三天,并且至少每两小时打开一次应用程序(清醒时) *还使模拟器运行了12个小时,结果相同

我已将背景获取间隔设置为:backgroundFetchIntervalMinimum

我已将后台获取包含在info.plist

我的代码在10秒内运行,所以我不认为长度是问题。

我使用错误的完成处理程序吗? (是否有办法在URLSession委托函数中调用.newData,.noData或.failed?) 有其他方法可以代替下载数据吗?

class AppDelegate: UIResponder, UIApplicationDelegate, 
UNUserNotificationCenterDelegate {

    var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.


  UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum)

    return true
}

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    print("running fetch")

    let userData : [String] = {"example", "example", "example"}

        let postString = "username1=\(userData[0])&text_password1=\(userData[1])&subcode=&timeoutin1=5&access1=1&city1=\(userData[2])&region1=\(region)"

    let url = URL(string: "www.example.com")!
    var request = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20)
    request.httpMethod = "post"
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpBody = parameters.data(using: .utf8)
    BackgroundSession.shared.start(request)
    print("finished")

        completionHandler(.newData)

}

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    if(identifier == "com.domain.app.bg") {
        BackgroundSession.shared.savedCompletionHandler = completionHandler
    } else {
        SecondBackgroundSession.shared.savedCompletionHandler = completionHandler
    }
}

}

这是我用来登录网站并解析网站响应的类         类BackgroundSession:NSObject {         静态让shared = BackgroundSession()

    static let identifier = "com.domain.app.bg"

    private var session: URLSession!

    var savedCompletionHandler: (() -> Void)?

    private override init() {
        super.init()

        let configuration = URLSessionConfiguration.background(withIdentifier: BackgroundSession.identifier)
        session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
    }

    func start(_ request: URLRequest) {
        print("start request")
        session.downloadTask(with: request).resume()
    }

     func startRequest(for urlString: String, method: String, parameters: String) {
         let url = URL(string: urlString)!
        var request = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20)
        request.httpMethod = method
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpBody = parameters.data(using: .utf8)
        SecondBackgroundSession.shared.start(request)
    }
}
    extension BackgroundSession: URLSessionDelegate {
        func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
        DispatchQueue.main.async {
            self.savedCompletionHandler?()
            self.savedCompletionHandler = nil
        }
    }
 }

extension BackgroundSession: URLSessionDownloadDelegate {
     func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        do {
            let responseNS = try NSString.init(contentsOf: location, encoding: String.Encoding.utf8.rawValue)
            let responseString : String = responseNS as String

            let doc = try SwiftSoup.parse(responseString)

            let form = try doc.select("form").first()

            var action = try form!.attr("action")

            action = String(action.dropFirst(2))

            let url = "https://example.com" + action

            let session = try form!.select("input").get(4).attr("value")
            let server = try form!.select("input").get(5).attr("value")
            let district = try form!.select("input").get(6).attr("value")
            let stud = try form!.select("input").get(9).attr("value")
            let track = try form!.select("input").get(13).attr("value")            

            let postString2 = "session=\(session)&server=\(server)&district=\(district)&stud=\(stud)&(track)&term=\(term)&ass="

             //this starts another request that navigates to anther page on the website that displays the user data
             startRequest(for: url, method: "post", parameters: postString2)

        } catch {
        }
    }
}

这是我用来完成用户数据下载的最后一个类。和上一堂课差不多

class SecondBackgroundSession: NSObject {
    static let shared = SecondBackgroundSession()

    static let identifier = "com.domain.app.sc"

    private var session: URLSession!

    var newData = false

    var savedCompletionHandler: (() -> Void)?

    override init() {
        super.init()

        let configuration = URLSessionConfiguration.background(withIdentifier: 
 SecondBackgroundSession.identifier)
        session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
    }

    func start(_ request: URLRequest) {
        print("start second request")
        session.downloadTask(with: request).resume()
    }

extension SecondBackgroundSession: URLSessionDelegate {
    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
        DispatchQueue.main.async {
            self.savedCompletionHandler?()
            self.savedCompletionHandler = nil
        }
    }
}

extension SecondBackgroundSession: URLSessionDownloadDelegate {
     func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        do {
             let contentString = try NSString.init(contentsOf: location, encoding: String.Encoding.utf8.rawValue)
            let doc : Document = try SwiftSoup.parse(contentString as String)
            //class used to compare data and send notifications if anything has changed
            let comp = Comparison()
            comp.setElements(input: doc)
         } catch {
         }
    }
}

该代码主要基于URLSession.datatask with request block not called in background

0 个答案:

没有答案