Ios SwiftUI MVVM将变量从ViewModel传递到API服务

Ios SwiftUI MVVM将变量从ViewModel传递到API服务,ios,swift,mvvm,swiftui,Ios,Swift,Mvvm,Swiftui,我对Swift&XCode非常陌生,在学习了几篇教程之后,我已经制作了一个带有API服务的MVVM体系结构,但是我无法将变量从ViewModel传递到API服务。我想传递var user&从LoginViewModel传递到apident enum APIEndpoint { case userLogin case menuList } extension APIEndpoint: RequestBuilder { var urlRequest: URLRequest

我对Swift&XCode非常陌生,在学习了几篇教程之后,我已经制作了一个带有API服务的MVVM体系结构,但是我无法将变量从ViewModel传递到API服务。我想传递var user&从LoginViewModel传递到apident

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
        }
        
    }
}
LoginView模型

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)
    }
}
请求生成器

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()
    }
}
协议登录服务{
var apiSession:APIService{get}
func login()->AnyPublisher
}
扩展登录服务{
func login()->AnyPublisher{
返回apiSession.request(使用:apident.userLogin)
.删除任何发布者()
}
}
蜂房服务

protocol APIService {
    func request<T: Decodable>(with builder: RequestBuilder, test: String) -> AnyPublisher<T, APIError>
}
协议服务{
func请求(使用builder:RequestBuilder,test:String)->AnyPublisher
}
阿皮塞恩

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()
    }
}
struct APISession:APIService{
func request(带builder:RequestBuilder)->AnyPublisher,其中T:Decodable{
let decoder=JSONDecoder()
decoder.keyDecodingStrategy=.convertFromSnakeCase
返回URLSession.shared
.dataTaskPublisher(适用于:builder.urlRequest)
.receive(在:DispatchQueue.main上)
.maperor{in.unknown}
.flatMap{data,response->AnyPublisher in
如果let response=response as?HTTPURLResponse{
if(200…299).contains(response.statusCode){
打印(字符串(数据:数据,编码:.utf8)??“”)
仅返回(数据)
.解码(类型:T.self,解码器:解码器)
.mapError{in.decodingError}
.删除任何发布者()
}否则{
返回失败(错误:apirerror.httpError(response.statusCode))
.删除任何发布者()
}
}
返回失败(错误:APIRROR.unknown)
.删除任何发布者()
}
.删除任何发布者()
}
}

提前感谢大家。

您应该在以下表单中更改您的枚举:

enum端点{
case userLogin(用户:字符串,密码:字符串)
案例专家
}
更改您的requestBuilder:

扩展API端点:RequestBuilder{ var urlRequest:urlRequest{ 切换自身{ case.userLogin(let user,let password): guard let url=url(字符串:https://jcouserapidev.oxxo.co.id/home/app") else{PremissionFailure(“无效URL格式”)} var-request=URLRequest(url:url) request.setValue(“application/json”,forHTTPHeaderField:“Content Type”) request.setValue(Constants.API_令牌,用于HttpHeaderField:“授权”) request.httpMethod=“POST” let body:[字符串:任意]=[“用户”:用户,“通过”:通过] 让rb=try!JSONSerialization.data(带jsonobject:body) request.httpBody=rb 退货申请 案例.菜单列表: guard let url=url(字符串:https://jcouserapidev.oxxo.co.id/home/app") else{PremissionFailure(“无效URL格式”)} var-request=URLRequest(url:url) request.setValue(“application/json”,forHTTPHeaderField:“Content Type”) request.setValue(Constants.API_令牌,用于HttpHeaderField:“授权”) request.httpMethod=“POST” 退货申请 } } }
在此之后,在所有
登录
功能中,您应该将
用户
密码
作为参数传递

谢谢您的回答,但我仍然无法从viewmodel中获取要传递到APIEndpoint的值,我需要在LoginViewModel和LoginService中做什么?我很抱歉,我真的是新手,我尝试过调整代码,但它只是不断弹出错误