Task is new ViewModifier in iOS15. SwiftUI

Apple added a new ViewModifier task(priority:_:) in iOS 15. This modifier can be added to any SwiftUI View.

task(priority:_:) avalible since iOS15+ macOS 12.0+ Mac Catalyst 15.0+ watchOS 8.0+ tvOS 15.0+

From official apple documentation:

Adds an asynchronous task to perform when this view appears.

func task(priority: TaskPriority = .userInitiated, _ action: @escaping () async -> Void) -> some View

A view that runs the specified action asynchronously when the view appears.

See details about parameters:

  1. Priority The task priority to use when creating the asynchronous task. The default priority is userInitiated.

All priorities list:

  1. Action A closure that SwiftUI calls as an asynchronous task when the view appears. SwiftUI automatically cancels the task if the view disappears before the action completes.

This modifier is a good point to start and to do some asynchronous job related to the view. You don’t have to worry about canceling asynchronous task, SwiftUI handles it out of the box.
SwiftUI cancels the task in case of the task doesn’t finish before SwiftUI removes the view or the view changes identity.

Example:

Show the list users of GitHub. Displays the login and avatar image for each user.

List code:

@State private var users: [User] = []

var body: some View {
    List(users) { user in
        HStack(spacing: 16) {
            AsyncImage(url: URL(string: user.avatarUrl)) { avatar in
                avatar
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .cornerRadius(16)
            } placeholder: {
                ProgressView()
            }
            .frame(width: 50, height: 50)
            
            Text(user.login)
                .font(.title2)
        }.padding(.init(top: 4, leading: 0, bottom: 4, trailing: 0))
    }.task {
        self.users = await loadUsers()
    }
}

We are interested in function loadUsers(). The loading of users starts when the List appears. First of all the function gets JSON of users from GitHub. After that, it decodes the JSON into objects and finally sets the result to the List's data source.

loadUsers() function:

func loadUsers() async -> [User] {
    guard let url = URL(string: "https://api.github.com/users") else { return [] }
    do {
        let (data, _) = try await URLSession.shared.data(from: url)
        return try JSONDecoder().decode([User].self, from: data)
    } catch {
        Swift.print(error)
        return []
    }
}

Result UsersList

Usermodel:

struct User: Codable, Identifiable {
    let id: Int
    let login: String
    let avatarUrl: String
    
    enum CodingKeys: String, CodingKey {
        case id
        case login
        case avatarUrl = "avatar_url"
    }
}

The model implements Codable protocol for decoding JSON. Enum CodingKeys is used to translate from the snake case 🐍 to the camel case 🐫.

Full source code

Thanks for reading! See you soon.