Search code examples
swift

What is type of result of withTaskGroup?


I have swift code that fetches data with URLSession and returns Result type. Code works and I want to extract it to the function.

private func getApiJsonStruct(endpoints: [MySettings]) async -> [MyStatusStruct] {
    
    var results: [MyStatusStruct] = []
    
    await withTaskGroup(of: Result<ApiJsonStruct, MyError>.self) { group in
        for cfg in endpoints {
            group.addTask {
                return await withCheckedContinuation { continuation in
                    self.httpGetInfo(baseUrl: cfg.host) { result in
                        continuation.resume(returning: result)
                    }
                }
            }
        }
        
        for await hbResult in group {
            switch hbResult {
                case .success(let answer):
                    print("OK.")
                    results.append(.init(status: true))
                    
                case .failure(let error):
                    switch error{
                        case .noConnection(let errUrl):
                            print("No connection.")
                            results.append(.init(status: false))
                    }
            }
        }
    }
    return results
}

When extracted to the function it produces error

Type of expression is ambiguous without a type annotation

Based in withCheckedContinuation, the continuation error is solved with

(continuation : CheckedContinuation<Result<ApiJsonStruct, MyError>, Never>)

That fix gives the same error on the group line. According to the withTaskGroup, not 100% sure, but this line fixes it

(group: inout TaskGroup<Result<ApiJsonStruct, MyError>>

Right now the word async is highlighted red with the same

Type of expression is ambiguous without a type annotation

How should I specify the type and where?


Solution

  • httpGetInfo determines the return type for the individual tasks for the group.

    The issue likely stems from accessing the array that is outside of the task group. This code will compile, you can match the types.

    struct MyService {
        private func getApiJsonStruct(endpoints: [MySettings]) async -> [MyStatusStruct] {
            return await withTaskGroup(of: Result<ApiJsonStruct, MyError>.self) { group in
                for cfg in endpoints {
                    group.addTask {
                        return await withCheckedContinuation { continuation in
                            self.httpGetInfo(baseUrl: cfg.host) { result in
                                continuation.resume(returning: result)
                            }
                        }
                    }
                }
                var results: [MyStatusStruct] = []
                for await hbResult in group {
                    switch hbResult {
                    case .success(let answer):
                        print("OK.")
                        results.append(.init(status: true))
                        
                    case .failure(let error):
                        switch error{
                        case .noConnection(let errUrl):
                            print("No connection.")
                            results.append(.init(status: false))
                        default:
                            results.append(.init(status: false))
                        }
                    }
                }
                return results
            }
            
        }
        func httpGetInfo(baseUrl: URL, completion: (Result<ApiJsonStruct, MyError>) -> Void) {
            completion(.failure(.someError))
        }
        
        struct ApiJsonStruct{
            let host: URL
        }
        enum MyError: LocalizedError {
            case someError
            case noConnection(Error)
        }
        struct MyStatusStruct {
            let status: Bool
        }
        struct MySettings {
            let host: URL
        }
    }