kuzdu
kuzdu

Reputation: 7524

Pass async function via parameter for SwiftUI component

I have a SwiftUI component with a button, which I want to be used in various places. When the button is executed, a different action should be performed depending on the view.

One solution is that I pass a ViewModel down to the component. However, the solution doesn't scale that well with different ViewModels.

The alternative to work with a callback I don't find so nice either. Because the component is very deep from the hierarchy.

My idea was to create a CommandAction class. However, I fail at the method signature.

My idea was this class.

class CommandActions {
    // MARK: Lifecycle
    init(action: @escaping (( _ parameter1: String) async throws -> String)) {
        self.action = action
    }

    // MARK: Internal
    let action: ( _ parameter1: String) async throws -> String
}

This function should be execute.

private func doSomeAction(parameter1: String) async throws -> String {
        await Task.sleep(seconds: 1)
        return "Some Result"
}

When I want to init the class, I got a failure.

CommandActions(action: doSomeAction(parameter1: "test"))

The failure is: Cannot convert value of type 'String' to expected argument type '(String) async throws -> String'

I tried different variations but I don't get it. The goal is to only call something like this in the SwiftUI class: commandActions.action

Upvotes: 10

Views: 8928

Answers (1)

kuzdu
kuzdu

Reputation: 7524

Thanks for the comment, I found the solution I was looking for.

public class CommandActions {
    // MARK: Lifecycle

    public init(action: @escaping () async -> Void) {
        self.action = action
    }

    // MARK: Public

    public let action: () async -> Void
}

Init the commands

public func getCommands() -> CommandActions {
        CommandActions { [self] in
            await myFunction()
        }
    }

And the function

private func myFunction() async {
  // do some stuff here
}

Upvotes: 18

Related Questions