Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Pass generic type T through withCheckedContinuation

I have a search for multiple types, so the general search method has a generic type T, and multiple simple methods call it specifying the type as needed. I’d like to delay search method’s start (debounce in Combine) and I’d like to hide this code as deep as I can.

I’m generally using async/await API in my project, only using Combine if I have to. I didn’t find a built-in solution for this using async/await so I’m gonna use Combine’s debounce. (Please let me know if there is a cleaner solution without Combine)

So I have to go from async/await to Combine and back. This requires to use withCheckedContinuation which loses the T and causes an error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

// simple generic specification using Event
func searchEvents(query: String) async -> [Event] {
    await search(query: query)
}

// simple generic specification using Artist
func searchArtists(query: String) async -> [Artist] {
    await search(query: query)
}

// debouncing layer between specifications and generic search
private func search<T>(query: String) async -> [T] where T: Codable, T: Identifiable  {
    await withCheckedContinuation { continuation in
        Debouncer().debounce(query) { query in
            Task {
                // Generic parameter 'T' could not be inferred
                let a = await self.performSearch(query: query) // <- error here
                continuation.resume(returning: a)
            }
        }
    }
}

// generic search function, details don't matter
private func performSearch<T>(query: String) async -> [T] where T: Codable, T: Identifiable {
    ...
}

// class performing simple debouncing
class Debouncer {

    static var shared = Debouncer()

    private var debounceSubscription: AnyCancellable?

    func debounce(_ string: String, block: (String) -> ()) {
        debounceSubscription?.cancel()
        debounceSubscription = Just(string)
            .debounce(for: .milliseconds(200), scheduler: DispatchQueue.global(qos: .background))
            .sink { string in
                block(string)
            }
    }
}

Is there an elegant way to make it auto-understand the type without passing it as a parameter (type: T.Type, query: String)?

>Solution :

Tell the compiler that performSearch will return an array of T

let a: [T] = await performSearch(query: query)

Now T in performSearch will be the same as T in search which the compiler can conclude what type it is.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading