Search code examples
arrayscombine

Swift Combine: combining two calls to create a new output


Let's say there is a struct with such definition:

struct CustomData {
    let data1: Int
    let data2: String
}

There we have these two methods:

func getInt() -> AnyPublisher<Int, Error> {
    return Just(Int.random(in: 0...100))
        .setFailureType(to: Error.self)
        .eraseToAnyPublisher()
}

func getString() -> AnyPublisher<String, Error> {
    return Just("\(Int.random(in: 200...400))")
        .setFailureType(to: Error.self)
        .eraseToAnyPublisher()
}

Is it possible to use Combine to get the output of these functions and create an object of type CustomData in a chain of calls?


Solution

  • You may want to look at the various combine and merge calls. For example, using combineLatest:

    struct ContentView: View {
        
        @State var result: CustomData?
        @State var cancellable: AnyCancellable?
        
        var body: some View {
            VStack {
                if let result {
                    Text("result: \(result.data1) \(result.data2)")
                }
            }
            .onAppear {
                cancellable =
                    getInt()
                    .combineLatest(getString())
                    .tryMap {
                        CustomData(data1: $0, data2: $1)
                    }
                    .sink(receiveCompletion: { err in
                        //
                    }, receiveValue: { customData in
                        self.result = customData
                    })
            }
        }
        
        struct CustomData {
            let data1: Int
            let data2: String
        }
        
        func getInt() -> AnyPublisher<Int, Error> {
            return Just(Int.random(in: 0...100))
                .setFailureType(to: Error.self)
                .eraseToAnyPublisher()
        }
    
        func getString() -> AnyPublisher<String, Error> {
            return Just("\(Int.random(in: 200...400))")
                .setFailureType(to: Error.self)
                .eraseToAnyPublisher()
        }
    }