SwiftUI:如何使用组合进行 POST API 调用?
首先,请检查我的代码。
这是 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 = "************"
let client_Secret = "********"
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
}
}
第二个是 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)
}
}
最后,这是数据模型
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
}
我尝试通过这种方式进行 POST API 调用。 但是,我在 DataService 类上收到错误 请检查这张图片。
在我看来,URLsession是错误的,但我不知道问题出在哪里。
我希望我能通过这个问题来理解 api 调用与合并! 谢谢。
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 = "************"
let client_Secret = "********"
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
}
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在您的
private func apiCall(text : String) {...}
中使用request
,如下所示:PS:不要显示您的
client_Secret
在您的代码中,立即删除它。in your
private func apiCall(text : String) {...}
use therequest
, like this:PS: do not show your
client_Secret
in your code, remove it now.在您的代码中检查您是否正在创建请求但没有在任何地方使用它。
使用:
URLSession.shared.dataTaskPublisher(for request: URL Request)
您正在调用 url,而不是请求。
In your code check that you are creating request but not using it any where.
Use:
URLSession.shared.dataTaskPublisher(for request: URL Request)
You are making calling for url not for the request.