I have a problem, I can't solve by myself. But I think there has to be a very simple solution. So simple I can't see it :-(
I have a function that's downloads a file from a webserver and stores it on the device. this function works:
func downloadFile (fileOnServer: String, fileOnDevice: URL) async {
if let dataURL = URL(string: fileOnServer) {
URLSession.shared.downloadTask(with: dataURL) { (tempFileUrl, response, error) in
if let dataTempFileUrl = tempFileUrl {
do {
let urlData = try Data(contentsOf: dataTempFileUrl)
try urlData.write(to: fileOnDevice)
// checkSavedFile(file: fileOnDevice)
print("download successfull")
} catch {
print("Error")
}
}
}.resume()
}
}
I call this function in a simple SwiftUI view:
truct UpdateView: View {
@State var text = "Loading"
var body: some View {
VStack{
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
Text(text)
}
.task()
{
print ("START downloadFile() ")
await downloadFile(fileOnServer: htmlLinkForJSON, fileOnDevice: downloadedJSON)
await downloadFile(fileOnServer: htmlLinkForCategories, fileOnDevice: downloadedCategories)
print ("END downloadFile()")
print ("---------")
print ("Start checkSavedFile()")
checkSavedFile(file: downloadedJSON)
checkSavedFile(file: downloadedCategories)
print ("END checkSavedFile()")
print ("---------")
}
}
}
Now my problem: As you can see on the console output the checkSavedFile() starts before the download ends. How can I pause my code till the downloads ends? Do you know what I mean?
START downloadFile()
END downloadFile()
---------
Start checkSavedFile()
checkSavedFile gestartet
file:///Users/Library/Developer/CoreSimulator/Devices/AB464055-A554-4B4B-9AB3-BF7FAD670A81/data/Containers/Data/Application/7C940BA4-99EB-4250-83CB-BA6D2AA9669B/Documents/downloadedJSON.txt available!
checkSavedFile gestartet
file:///Users/Library/Developer/CoreSimulator/Devices/AB464055-A554-4B4B-9AB3-BF7FAD670A81/data/Containers/Data/Application/7C940BA4-99EB-4250-83CB-BA6D2AA9669B/Documents/downloadedCategories.txt available!
END checkSavedFile()
---------
2022-01-04 20:27:17.573376 0100 Blindzeln_Prototyp[4296:186653] [boringssl] boringssl_metrics_log_metric_block_invoke(151) Failed to log metrics
download successfull
download successfull
CodePudding user response:
You have to make downloadFile really async by using the appropriate async URLSession API. The completion handler API doesn't wait.
enum URLError : Error {
case badURL
}
func downloadFile (fileOnServer: String, fileOnDevice: URL) async throws {
guard let dataURL = URL(string: fileOnServer) else { throw URLError.badURL }
let (dataTempFileUrl, _) = try await URLSession.shared.download(from: dataURL)
try FileManager.default.moveItem(at: dataTempFileUrl, to: fileOnDevice)
}
In the task you have add a do - catch block to handle the error(s)
.task()
{
do {
print ("START downloadFile() ")
try await downloadFile(fileOnServer: htmlLinkForJSON, fileOnDevice: downloadedJSON)
try await downloadFile(fileOnServer: htmlLinkForCategories, fileOnDevice: downloadedCategories)
print ("END downloadFile()")
print ("---------")
print ("Start checkSavedFile()")
checkSavedFile(file: downloadedJSON)
checkSavedFile(file: downloadedCategories)
print ("END checkSavedFile()")
print ("---------")
} catch {
print(error)
}
}
