iOS Development

Swift async/await what it the alternative of DispatchQueue.important.async

You requested:

Can I nonetheless use DispatchQueue.important.async?

If you’re in an async technique and need to dispatch one thing to the primary queue, probably the most literal equal can be:

MainActor.run { ... }

However it’s extra prudent to easily mark the strategy (or its class) with @MainActor. Not solely will this be sure that it runs it on the primary thread, however you get compile-time warnings should you try to name it from the flawed actor.

So, in case your view mannequin is marked with @MainActor, the guide operating of the duty on the MainActor turns into pointless. That is very true when coping with revealed properties of an noticed object.

For instance, contemplate:

@MainActor
class ViewModel: ObservableObject {
    @Printed var values: [Int] = []

    func fetchData() async {
        let foo = await ...
        values = foo.values
    }
}

After which

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()

    var physique: some View {
        Checklist {
            ...
        }
        .refreshable {
            await viewModel.fetchData()
        }

    }
}

(Observe, I made fetchData an async technique and await it inside refreshable in order that the spinner precisely displays when the async course of is operating.)

See WWDC 2021 video Swift concurrency: Replace a pattern app. That’s admittedly illustrating the transition of a UIKit app, however consists of examples of @MainActor and MainActor.run.


Observe, whereas @MainActor, largely eliminates the necessity for MainActor.run { … }, there are nonetheless some situations the place you may use this run sample. Particularly, if you’re on another actor and need to run, for instance, three separate @MainActor features in succession on the primary thread, you possibly can wrap the sequence of them inside a single MainActor.run { … } block, thereby operating all three with a single dispatch to the primary actor, slightly than three separate calls.


Above, I targeted on the salient parts, however right here is my full MCVE:

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()

    var physique: some View {
        Checklist {
            ForEach(viewModel.values, id: .self) { worth in
                Textual content("(worth)")
            }
        }
        .refreshable {
            await viewModel.fetchData()
        }

    }
}

struct Foo: Decodable{
    let json: [Int]
}

@MainActor
class ViewModel: ObservableObject {
    @Printed var values: [Int] = []

    func fetchData() async {
        do {
            let foo = strive await object(Foo.self, for: request)
            values = foo.json
        } catch {
            print(error)
        }
    }

    func object<T: Decodable>(_ sort: T.Kind, for request: URLRequest) async throws -> T {
        let (information, response) = strive await URLSession.shared.information(for: request)

        guard let response = response as? HTTPURLResponse else {
            throw URLError(.badServerResponse)
        }

        guard 200 ... 299 ~= response.statusCode else {
            throw ApiError.failure(response.statusCode, information)
        }

        return strive JSONDecoder().decode(T.self, from: information)
    }

    var request: URLRequest = {
        let url = URL(string: "https://httpbin.org/something")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.httpBody = "[1,2,3,4,5]".information(utilizing: .utf8)
        request.addValue("utility/json", forHTTPHeaderField: "Content material-Kind")
        request.addValue("utility/json", forHTTPHeaderField: "Settle for")

        return request
    }()
}

enum ApiError: Error {
    case failure(Int, Knowledge)
}

Credit: www.ismmailgsm.com

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button