我对 Swift 和 XCode 非常陌生,在学习了几个教程之后,我制作了一个带有 API 服务的 MVVM 架构,但是我无法将我的变量从 ViewModel 传递给我的 API 服务。我想传递 var 用户并从 LoginViewModel 传递到 APIEndpoint
登录视图模型
class LoginViewModel: ObservableObject, LoginService {
// I want to send this 2 variables to APIEndpoint
@Published var user = ""
@Published var pass = ""
var cancellables = Set<AnyCancellable>()
init(apiSession: APIService = APISession()) {
self.apiSession = apiSession
}
func login() {
let cancellable = self.login()
.sink(receiveCompletion: { result in
switch result {
case .failure(let error):
print("Handle error: \(error)")
case .finished:
break
}
}) { (detail) in
print(detail)
}
cancellables.insert(cancellable)
}
}
API端点
enum APIEndpoint {
case userLogin
case menuList
}
extension APIEndpoint: RequestBuilder {
var urlRequest: URLRequest {
switch self {
case .userLogin:
guard let url = URL(string: "https://jcouserapidev.oxxo.co.id/home/app")
else {preconditionFailure("Invalid URL format")}
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(Constants.API_TOKEN, forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
// I want to pass the variables here, how??
let body: [String: Any] = ["user": $user, "pass": $pass]
let rb = try! JSONSerialization.data(withJSONObject: body)
request.httpBody = rb
return request
case .menuList:
guard let url = URL(string: "https://jcouserapidev.oxxo.co.id/home/app")
else {preconditionFailure("Invalid URL format")}
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(Constants.API_TOKEN, forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
return request
}
}
}
请求生成器
protocol RequestBuilder {
var urlRequest: URLRequest {get}
}
登录服务
protocol LoginService {
var apiSession: APIService {get}
func login() -> AnyPublisher<LoginAPIResponse, APIError>
}
extension LoginService {
func login() -> AnyPublisher<LoginAPIResponse, APIError> {
return apiSession.request(with: APIEndpoint.userLogin)
.eraseToAnyPublisher()
}
}
API服务
protocol APIService {
func request<T: Decodable>(with builder: RequestBuilder, test: String) -> AnyPublisher<T, APIError>
}
APISession
struct APISession: APIService {
func request<T>(with builder: RequestBuilder) -> AnyPublisher<T, APIError> where T: Decodable {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return URLSession.shared
.dataTaskPublisher(for: builder.urlRequest)
.receive(on: DispatchQueue.main)
.mapError { _ in .unknown }
.flatMap { data, response -> AnyPublisher<T, APIError> in
if let response = response as? HTTPURLResponse {
if (200...299).contains(response.statusCode) {
print(String(data: data, encoding: .utf8) ?? "")
return Just(data)
.decode(type: T.self, decoder: decoder)
.mapError {_ in .decodingError}
.eraseToAnyPublisher()
} else {
return Fail(error: APIError.httpError(response.statusCode))
.eraseToAnyPublisher()
}
}
return Fail(error: APIError.unknown)
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}
}
谢谢大家。