Мне нужно выполнять задачу периодически, если быть точным, раз в день, поэтому я реализовал фоновую выборку с minimumBackgroundFetchInterval
из 23 часов.Это делается, когда я симулирую фоновую выборку с моим приложением на переднем плане.
Но когда мое приложение находится в фоновом режиме, только метод application(_ application:, performFetchWithCompletionHandler)
вызывается, как и должно быть, а метод urlSession(_ session:, downloadTask:, didFinishDownloadingTo:)
либо не вызываетне вызывается вообще или вызывается, а затем приостанавливается в некоторой случайной точке выполнения. Когда приложение возвращается на передний план, оно продолжает выполняться.
Это происходит как на симуляторе, так и на устройстве.
Ниже приведен мой код с обоими вышеупомянутыми функциями.
var sviBrojevi = EncodingKontakt(provjeri: [])
var completionHandler: (UIBackgroundFetchResult) -> Void = { result in
return
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
let container = persistentContainer
let context = container.viewContext
sviBrojevi = EncodingKontakt(provjeri: [])
let request: NSFetchRequest<TelefonskiBroj> = TelefonskiBroj.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "ime", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))]
do{
let matches = try context.fetch(request)
if matches.count > 0 {
for match in matches{
sviBrojevi.provjeri.append(FetchedContact(ime: match.ime!, brojevi: [match.broj!]))
}
}
}catch {
print("Could not load data!")
}
guard let url = URL(string: "") else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.setValue("", forHTTPHeaderField: "Authorization")
let data = try? JSONEncoder().encode(sviBrojevi)
urlRequest.httpBody = data
let backgroundtask = urlSession.downloadTask(with: urlRequest)
backgroundtask.resume()
}
var numberOfContactsChanged = 0
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
var kontakti = DecodingKontakt(provjereno: [])
do{
let contents = try Data.init(contentsOf: location)
kontakti = try JSONDecoder().decode(DecodingKontakt.self, from: contents)
}catch let error{
print(error.localizedDescription)
completionHandler(.failed)
}
var promijenjeniBrojevi = [String]()
var brojac = 0
let sviKontakti = kontakti.provjereno
persistentContainer.performBackgroundTask { [weak self] (context) in
for index in sviKontakti.indices{
let contact = sviKontakti[index]
let number = self!.sviBrojevi.provjeri[index].brojevi[0] //GRESKA
let request: NSFetchRequest<TelefonskiBroj> = TelefonskiBroj.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "ime", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))]
request.predicate = NSPredicate(format: "ime = %@ AND broj = %@", contact.ime, number)
// request.returnsObjectsAsFaults = false
do{
let match = try context.fetch(request)
if match.count > 0 {
assert(match.count == 1, "AppDelegate.urlSession -- database inconsistency")
if match[0].operater != contact.brojevi[0]{//, match[0].operater != nil{
let obavjestenje = Obavjestenja(context: context)
obavjestenje.broj = number
obavjestenje.datumPromjene = Date()
obavjestenje.stariOperator = match[0].operater
obavjestenje.noviOperator = contact.brojevi[0]
obavjestenje.ime = match[0].ime
if let ime = match[0].ime {
promijenjeniBrojevi.append(ime)
}
let badgeNum = ImenikTableViewController.defaults.integer(forKey: "obavjestenja") + 1
ImenikTableViewController.defaults.set(badgeNum, forKey: "obavjestenja")
obavjestenje.sekcija = ""
brojac += 1
ImenikTableViewController.defaults.set(brojac, forKey: "obavjestenja")
}
match[0].operater = contact.brojevi[0]
match[0].vrijemeProvjere = Date()
}
}catch {
self?.completionHandler(.failed)
print("Could not load data!")
}
}
try? context.save()
if promijenjeniBrojevi.count > 0{
let center = UNUserNotificationCenter.current()
//create the content for the notification
let content = UNMutableNotificationContent()
content.title = "Operator"
content.sound = UNNotificationSound.default
content.badge = NSNumber(integerLiteral: promijenjeniBrojevi.count)
if promijenjeniBrojevi.count == 1{
content.body = "\(promijenjeniBrojevi[0]) je promijenio/la mrežu"
}else if promijenjeniBrojevi.count == 2{
content.body = "\(promijenjeniBrojevi[0]) i \(promijenjeniBrojevi[1]) su promijenili mrežu"
}else{
content.body = "\(promijenjeniBrojevi[0]) i drugi su promijenili mrežu"
}
//notification trigger can be based on time, calendar or location
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(5), repeats: false)
//create request to display
let request = UNNotificationRequest(identifier: "Obavjestenje", content: content, trigger: trigger)
//add request to notification center
center.add(request) { (error) in
if error != nil {
print("error \(String(describing: error))")
}
}
self?.completionHandler(.newData)
}
NotificationCenter.default.post(name: Notification.backFetch, object: nil)
}
}