Я реализовал фоновые задачи в Swift, и все работает отлично, функция выполняется, когда я запускаю приложение в фоновом режиме на реальном устройстве. Когда я хочу загрузить изображение в хранилище Firebase, используя putData в фоновой задаче типа BGAppRefreshTask, обработчик завершения putData вызывается только тогда, когда приложение возвращается на передний план и не выполняется в фоновой задаче.
Как я могу обеспечить выполнение задачи загрузки во время фоновой задачи? Спасибо всем за помощь !!
Здесь я регистрирую задачу
//register for background tasks
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.foodnotifs.checknewfotos", using: nil) {(task) in
self.handleAppRefreshTask(task: task as! BGAppRefreshTask)
print("task registered")
//
}
Здесь я отправляю задачу
let checkFotosTask = BGAppRefreshTaskRequest(identifier: "com.foodnotifs.checknewfotos")
checkFotosTask.earliestBeginDate = Date(timeIntervalSinceNow: 10*60)//every 10 min
do{
try BGTaskScheduler.shared.submit(checkFotosTask)
} catch{
print("unable to submit task: \(error.localizedDescription)")
}
Теперь вот фактическая фоновая задача, которая выполняется:
func handleAppRefreshTask(task: BGAppRefreshTask)
{
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd hh:mm:ss"
let now:String = df.string(from: Date())
let user = Auth.auth().currentUser
if(user == nil){
task.setTaskCompleted(success: false)} //if no user for some reason, end task
let uid = user!.uid
let databaseRef = Database.database().reference()
databaseRef.child("users/" + uid + "/BACKGROUNDFETCHEDIMAGES/" + now).setValue(numberOfNewImages)
print("number of new images written to database")
let newAsset = fetchResults.object(at: 0)
let size = CGSize(width: newAsset.pixelWidth/3, height: newAsset.pixelHeight/3)
PHImageManager.default().requestImage(for: newAsset, targetSize: (size), contentMode: .aspectFill, options: nil, resultHandler: { image, _ in
print("image retrieved successfully from phmanager")
let storageRef = Storage.storage().reference(forURL: "gs://foodnotifs.appspot.com")
let storageProfileRef = storageRef.child(uid).child(now)
//create some self defined metadata
let metadata = StorageMetadata()
metadata.contentType = "image/jpg"
metadata.customMetadata = ["uid": uid, "date":now, "image_name":now]
//now upload the image to storage and update database entry
//let uploadTask = storageProfileRef.putData(image!.jpegData(compressionQuality: 0.4)!, metadata: metadata)
//CODE EXECUTES UP TO HERE, completion handler of putData is not executed
storageProfileRef.putData(image!.jpegData(compressionQuality: 0.4)!, metadata: metadata) { (uploadedMetadata, error) in
if error != nil{
print("getting error uploading to storage")
print(error!.localizedDescription)
return
}
else{
print("upload to storage successful")
var DLurl:String = ""
storageProfileRef.downloadURL { (url,error) in
guard let DLurl = url?.absoluteString else{
print("error getting download url for uploaded image")
print(error!.localizedDescription)
return
}
print("download url is: " + DLurl)
//successful upload, now update the database of this user with the image url
databaseRef.child("users").child(uid).child("IMAGE_URLs").child(now).setValue(DLurl){ (error, ref) in
if error == nil {
//on sucess, also save url to most recent
print("uploaded to database")
databaseRef.child("users").child(user!.uid).child("IMAGE_URLs").child("MOST_RECENT").setValue(DLurl)
}
else{
print("error in uploading to database")
print(error!.localizedDescription)
}
}//database updated succssfully
} //download url gotten successfully
} //succesful upload
}//storage profile ref putdata completion
})
}
else{
print("no camera roll found")
}
//CODE CONTINUES HERE AND REACHES THE END OF THE FUNCTION WITHOUT UPLOADING THE IMAGE
self.appWillBecomeInactive() //schedule again
print("background task finished")
task.setTaskCompleted(success: true) //task completed
}//end function