'SwiftUI : How I can do POST API CALL with Combine?

Firstly, Please check my code.

This is Dataservice Utility

import Foundation
import Combine
import SwiftUI

class PapagoDataService {
    
    @Published var translated : TranslateModel?
    
    static let instance = PapagoDataService()
    
    var cancellables = Set<AnyCancellable>()
    
    private init() {
        apiCall(text: "안녕하세요")
    }
    
    private func apiCall(text : String) {
        
        let param = "source=ko&target=en&text=\(text)"
        let paramData = param.data(using: .utf8)
        let client_Id = "uper2EKrAl57W_VGdNRw"
        let client_Secret = "Vc7Ztinlmz"

        guard let url = URL(string: "https://openapi.naver.com/v1/papago/n2mt")
        else { return }
        print("0")
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.httpBody = paramData
        request.addValue(client_Id, forHTTPHeaderField: "X-Naver-Client-Id")
       
        
        print("1")
        URLSession.shared.dataTaskPublisher(for: url)
            .subscribe(on: DispatchQueue.global(qos: .background))
            .tryMap(handleOutput)
            .decode(type: TranslateModel.self, decoder: JSONDecoder())
            .sink { (completion) in
                switch completion {
                case .finished:
                    break
                case .failure(let error):
                    print("Error to download")
                }
            } receiveValue: { [weak self] (translatedData) in
                self?.translated = translatedData
            }
            .store(in: &cancellables)
    }
    
    func handleOutput(output : URLSession.DataTaskPublisher.Output) throws -> Data {
        
        guard let response = output.response as? HTTPURLResponse,
              response.statusCode >= 200 && response.statusCode < 300  else {
                  throw URLError(.badServerResponse)
              }
        return output.data
    }
    
}

Second one is ViewModel

import Foundation
import Combine

class HomeViewModel : ObservableObject {
    
    @Published var translated : TranslateModel?
    
    let dataService = PapagoDataService.instance
    
    var cancellable = Set<AnyCancellable>()
    
    init() {
        addSubscriber()
    }
    
    private func addSubscriber() {
        dataService.$translated
            .sink { [weak self] (receiveModel) in
                DispatchQueue.main.async {
                    self?.translated = receiveModel
                }
            }
            .store(in: &cancellable)
    }
}

Last, This is Model of data

import Foundation

struct TranslateModel : Codable {
    
    let message: Message
}

// MARK: - Message
struct Message: Codable {
    
    let type, service, version: String
    let result: Result

    enum CodingKeys: String, CodingKey {
        case type = "@type"
        case service = "@service"
        case version = "@version"
        case result
    }
}

// MARK: - Result
struct Result: Codable {
    let translatedText: String
}

enter image description here

I tried to do POST API Call with combine by this way. But, I got the error on DataService Class Check this Picture please.

In my opinion, URLsession is wrong, but I don't know what is the problem.

I hope I can serve this problem to understand api call with combine! Thank you.



Solution 1:[1]

in your private func apiCall(text : String) {...} use the request, like this:

 URLSession.shared.dataTaskPublisher(for: request)  // <--- here

PS: do not show your client_Secret in your code, remove it now.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 workingdog support Ukraine