'Swift: task {} before iOS 15?

I am following tutorials to understand SwiftUI, and specifically how to call an API when a view appears.

I saw this:

List(results, id: \.trackId) { item in
    ListRow(item)
}
.task {
    // perform API here
}

But as my app targets iOS 14, I get this error:

'task(priority:_:)' is only available in iOS 15.0 or newer

So what could I do instead? Thank you for your help



Solution 1:[1]

import SwiftUI

struct ContentView: View {
    
    @State var results = [TaskEntry]()
  
    var body: some View {
        List(results, id: \.id) { item in
            VStack(alignment: .leading) {
                Text(item.title)
            }
// this one onAppear you can use it
        }.onAppear(perform: loadData)
    }
    
  
    func loadData() {
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/todos") else {
            print("Your API end point is Invalid")
            return
        }
        let request = URLRequest(url: url)

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let response = try? JSONDecoder().decode([TaskEntry].self, from: data) {
                    DispatchQueue.main.async {
                        self.results = response
                    }
                    return
                }
            }
        }.resume()
    }
    
}

Solution 2:[2]

async await is available for iOS 13+.

https://developer.apple.com/documentation/swift/task

if you need to use an async call is wrap the call in Task

.onAppear(){
    Task{
        //Your async code here
        // await yourFuncHere()
    }
}     

.onAppear is a bit un reliable so I might opt for an init of an ObservableObject as an alternative.

Solution 3:[3]

You can write a version of task { } that works for iOS 13, iOS 14 and uses apple's version for iOS 15:

extension View {
    @available(iOS, deprecated: 15.0, message: "This extension is no longer necessary. Use API built into SDK")
    func task(priority: TaskPriority = .userInitiated, _ action: @escaping @Sendable () async -> Void) -> some View {
        self.onAppear {
            Task(priority: priority) {
                await action()
            }
        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Zeeshan Ahmed
Solution 2
Solution 3 luizParreira