Swift store closure with parameter packs

63 Views Asked by At

I would like to create a closure type that is always called on the main thread using the new parameter packs introduced in Swift 5.9. E.g.

protocol Repository {
    func loadData(completion: MainClosure<Result<String, Error>>)
}

class MockRepository: Repository {
    func loadData(completion: MainClosure<Result<String, Error>>) {
        DispatchQueue.global().async {
            // Load some data...

            completion(.success("foo")) // Calls on the main thread
        }
    }
}

This is my current implementation, but I get 2 errors.

public struct MainClosure<each T> {
    private let closure: (repeat each T) -> Void

    public init(_ closure: @escaping (repeat each T) -> Void) {
        self.closure = closure // Error: Type of expression is ambiguous without a type annotation
    }

    public func callAsFunction(_ parameter: repeat each T) -> Void {
        DispatchQueue.main.async {
            self.closure(each parameter) // Error: Cannot pass value pack expansion to non-pack parameter of type 'repeat each T'
        }
    }
}

If I don't define the init method the compiler manages to do it for me, so there is some way, but I need to define it as public.

How can I resolve these issues to a) store the closure, b) pass the parameters to it from callAsFunction?

0

There are 0 best solutions below