MVC网络Swift

MVC网络Swift,swift,Swift,我在模型中声明了这个网络类 class Networking { func response (url : String ) { guard let url = URL(string: url) else {return} URLSession.shared.dataTask(with: url, completionHandler: urlPathCompletionHandler(data:response:error:)).resume()

我在模型中声明了这个网络类

class Networking {
    func response (url : String ) {
        guard let url = URL(string: url) else {return}
        URLSession.shared.dataTask(with: url, completionHandler: urlPathCompletionHandler(data:response:error:)).resume()
    }

    func urlPathCompletionHandler (data : Data?  , response: URLResponse? , error: Error? ) {
        guard let data = data else {return }
        do {
            let jsondecoder = JSONDecoder()
        }catch {
            print("Error \(error)")
        }
    }
}
在控制器中。我有一个我声明的用户数组,我希望控制器从ModelNetworking类调用,而不是在控制器内部进行联网。这是我的控制器的一部分:

var users = [Users]()
var networking : Networking()
@IBOutlet weak var tableview : UITableView!
override func viewDidLoad() {
    super.viewDidLoad()
    tableview.delegate = self
    tableview.dataSource = self

}
func getFromModel() {
  var vm = networking.response()   
}


我想要一种调用networking类并返回用户数组的方法,我可以将其设置为上面的users数组,并使用它填充表视图。如果我想在控制器内执行此操作,这将很容易,但我不确定如何从Model Networking类返回一组用户。

您需要修改网络类,如下所示:

班级网络{
func响应(url:字符串,完成:((T)->Void)?){
guard let url=url(字符串:url)else{return}
URLSession.shared.dataTask(在中带有:url,completionHandler:{(数据,响应,错误))
urlPathCompletionHandler(数据:数据,响应:响应,错误:错误,完成:完成)
})1.简历()
}
func urlPathCompletionHandler(数据:数据?,响应:URLResponse?,错误:错误?,完成:((T)->Void)?){
guard let data=data else{return}
做{
让jsondecoder=jsondecoder()
//用于解码用户的伪代码
完成?(解码对象)
}抓住{
打印(“错误\(错误)”)
}
}
}
这样称呼它:

func getFromModel(){
networking.response(url:){(用户:[用户])在
self.users=用户
}
}

您需要像这样修改网络类:

班级网络{
func响应(url:字符串,完成:((T)->Void)?){
guard let url=url(字符串:url)else{return}
URLSession.shared.dataTask(在中带有:url,completionHandler:{(数据,响应,错误))
urlPathCompletionHandler(数据:数据,响应:响应,错误:错误,完成:完成)
})1.简历()
}
func urlPathCompletionHandler(数据:数据?,响应:URLResponse?,错误:错误?,完成:((T)->Void)?){
guard let data=data else{return}
做{
让jsondecoder=jsondecoder()
//用于解码用户的伪代码
完成?(解码对象)
}抓住{
打印(“错误\(错误)”)
}
}
}
这样称呼它:

func getFromModel(){
networking.response(url:){(用户:[用户])在
self.users=用户
}
}

好的,有一些想法:

  • 您的
    response
    方法正在执行异步网络请求,因此需要为其提供一个完成处理程序参数。因此,我可以建议如下:

    class Networking {
        enum NetworkingError: Error {
            case invalidURL
            case failed(Data?, URLResponse?)
        }
    
        private let parsingQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".parsing")
    
        // response method to handle network stuff
    
        func responseData(_ string: String, completion: @escaping (Result<Data, Error>) -> Void) {
            guard let url = URL(string: string) else {
                completion(.failure(NetworkingError.invalidURL))
                return
            }
    
            URLSession.shared.dataTask(with: url) { data, response, error in
                DispatchQueue.main.async {
                    if let error = error {
                        completion(.failure(error))
                        return
                    }
    
                    guard
                        let responseData = data,
                        let httpResponse = response as? HTTPURLResponse,
                        200 ..< 300 ~= httpResponse.statusCode
                    else {
                        completion(.failure(NetworkingError.failed(data, response)))
                        return
                    }
    
                    completion(.success(responseData))
                }
            }.resume()
        }
    
        // response method to handle the JSON parsing
    
        func response<T: Decodable>(of type: T.Type, from string: String, completion: @escaping (Result<T, Error>) -> Void) {
            responseData(string) { result in
                switch result {
                case .failure(let error):
                    completion(.failure(error))
    
                case .success(let data):
                    self.parsingQueue.async {
                        do {
                            let responseObject = try JSONDecoder().decode(T.self, from: data)
                            DispatchQueue.main.async {
                                completion(.success(responseObject))
                            }
                        } catch let parseError {
                            DispatchQueue.main.async {
                                completion(.failure(parseError))
                            }
                        }
                    }
                }
            }
        }
    }
    
  • 然后
    getFromModel
    (最好称为
    getFromRepository
    或类似的东西)可以用以下方法解析它:

    networking.response(of: ResponseObject<[User]>.self, from: urlString) { result in
        switch result {
        case .failure(let error):
            print(error)
    
        case .success(let responseObject):
            let users = responseObject.data
            // do something with users
        }
    }
    

  • 现在,很明显,在您的示例中,模型类型可能会有所不同,但是您没有分享JSON的外观,因此我不得不猜测,但希望上面的内容能够说明一般的想法。制作一个基于泛型的网络API,并为其异步响应提供一个完成处理程序。

    好的,有一些想法:

  • 您的
    response
    方法正在执行异步网络请求,因此需要为其提供一个完成处理程序参数。因此,我可以建议如下:

    class Networking {
        enum NetworkingError: Error {
            case invalidURL
            case failed(Data?, URLResponse?)
        }
    
        private let parsingQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".parsing")
    
        // response method to handle network stuff
    
        func responseData(_ string: String, completion: @escaping (Result<Data, Error>) -> Void) {
            guard let url = URL(string: string) else {
                completion(.failure(NetworkingError.invalidURL))
                return
            }
    
            URLSession.shared.dataTask(with: url) { data, response, error in
                DispatchQueue.main.async {
                    if let error = error {
                        completion(.failure(error))
                        return
                    }
    
                    guard
                        let responseData = data,
                        let httpResponse = response as? HTTPURLResponse,
                        200 ..< 300 ~= httpResponse.statusCode
                    else {
                        completion(.failure(NetworkingError.failed(data, response)))
                        return
                    }
    
                    completion(.success(responseData))
                }
            }.resume()
        }
    
        // response method to handle the JSON parsing
    
        func response<T: Decodable>(of type: T.Type, from string: String, completion: @escaping (Result<T, Error>) -> Void) {
            responseData(string) { result in
                switch result {
                case .failure(let error):
                    completion(.failure(error))
    
                case .success(let data):
                    self.parsingQueue.async {
                        do {
                            let responseObject = try JSONDecoder().decode(T.self, from: data)
                            DispatchQueue.main.async {
                                completion(.success(responseObject))
                            }
                        } catch let parseError {
                            DispatchQueue.main.async {
                                completion(.failure(parseError))
                            }
                        }
                    }
                }
            }
        }
    }
    
  • 然后
    getFromModel
    (最好称为
    getFromRepository
    或类似的东西)可以用以下方法解析它:

    networking.response(of: ResponseObject<[User]>.self, from: urlString) { result in
        switch result {
        case .failure(let error):
            print(error)
    
        case .success(let responseObject):
            let users = responseObject.data
            // do something with users
        }
    }
    

  • 现在,很明显,在您的示例中,模型类型可能会有所不同,但是您没有分享JSON的外观,因此我不得不猜测,但希望上面的内容能够说明一般的想法。创建一个基于泛型的网络API,并为其异步响应提供一个完成处理程序。

    但现在Networking类只支持下载和解码用户对象。使用泛型更新。但现在Networking类只支持下载和解码用户对象。使用泛型更新。
    AF.request(urlString).responseDecodable(of: ResponseObject<[User]>.self) { response in
        switch response.result {
        case .failure(let error):
            print(error)
    
        case .success(let responseObject):
            let users = responseObject.data
        }
    }