在ios中,从不同的视图控制器多次调用同一Web服务(而不是同时调用)
我只是想知道在不同的时间从不同的视图控制器调用相同的Web服务的最佳方式是什么。我应该遵循什么架构或设计?我不想在每个视图控制器中编写相同的代码 我将编写一个网络管理器类,它将web服务参数(如果有的话)作为参数 这是一个粗略的架构示例在ios中,从不同的视图控制器多次调用同一Web服务(而不是同时调用),ios,swift,xcode,rest,Ios,Swift,Xcode,Rest,我只是想知道在不同的时间从不同的视图控制器调用相同的Web服务的最佳方式是什么。我应该遵循什么架构或设计?我不想在每个视图控制器中编写相同的代码 我将编写一个网络管理器类,它将web服务参数(如果有的话)作为参数 这是一个粗略的架构示例 class YourNetworkManager { public func callSpecificWebService(argument : Type?, [optional closure to handle results]) {
class YourNetworkManager {
public func callSpecificWebService(argument : Type?, [optional closure to handle results]) {
// Generate the actual URL to be called here. Usually by
// appending a suffix to some constant base url
// The web service call mechanism goes here.
// This could either use the NSURLSession API
// or some third party library such as Alamofire
// Process the generic response conditions from the web service
// here. Pass on the specific parts to the calling method.
}
}
正如我提到的,这是一个粗糙的例子。你能制造的东西越模块化,它就会越好 我将编写一个网络管理器类,它将web服务参数(如果有的话)作为参数 这是一个粗略的架构示例
class YourNetworkManager {
public func callSpecificWebService(argument : Type?, [optional closure to handle results]) {
// Generate the actual URL to be called here. Usually by
// appending a suffix to some constant base url
// The web service call mechanism goes here.
// This could either use the NSURLSession API
// or some third party library such as Alamofire
// Process the generic response conditions from the web service
// here. Pass on the specific parts to the calling method.
}
}
正如我提到的,这是一个粗糙的例子。你能制造的东西越模块化,它就会越好 您使用Alamofire吗?如果是,那么我有一个很好的方法,用NetworkHelper类编写
import Foundation
import Alamofire
open class NetworkHelper {
class var sharedManager: NetworkHelper {
struct Static{
static let instance: NetworkHelper = NetworkHelper()
}
return Static.instance
}
func request(_ method: HTTPMethod
, _ URLString: String
, parameters: [String : AnyObject]? = [:]
, headers: [String : String]? = [:]
, onView: UIView?, vc: UIViewController, completion:@escaping (Any?) -> Void
, failure: @escaping (Error?) -> Void) {
let URL = BASE_PATH + URLString
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
switch response.result {
case .success:
completion(response.result.value!)
case .failure(let error):
failure(error)
guard error.localizedDescription == JSON_COULDNOT_SERIALISED else {
return
}
}
}
}
}
您是否使用Alamofire?如果是,那么我有一个很好的方法,用NetworkHelper类编写
import Foundation
import Alamofire
open class NetworkHelper {
class var sharedManager: NetworkHelper {
struct Static{
static let instance: NetworkHelper = NetworkHelper()
}
return Static.instance
}
func request(_ method: HTTPMethod
, _ URLString: String
, parameters: [String : AnyObject]? = [:]
, headers: [String : String]? = [:]
, onView: UIView?, vc: UIViewController, completion:@escaping (Any?) -> Void
, failure: @escaping (Error?) -> Void) {
let URL = BASE_PATH + URLString
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
switch response.result {
case .success:
completion(response.result.value!)
case .failure(let error):
failure(error)
guard error.localizedDescription == JSON_COULDNOT_SERIALISED else {
return
}
}
}
}
}
如果使用Alamofire库,我可以建议使用
class NetworkManager {
static let shared = NetworkManager()
static let alamofireManager: SessionManager = {
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.timeoutIntervalForRequest = TimeInterval(_TIMEOUT)
sessionConfiguration.timeoutIntervalForResource = TimeInterval(_TIMEOUT)
return Alamofire.SessionManager(configuration: sessionConfiguration)
}()
func performRequest(url: String,
method: HTTPMethod = .get,
parameters: [String: Any] = [String: Any](),
encoding: ParameterEncoding = URLEncoding.default,
contentType: String? = nil,
headers: HTTPHeaders = [String: String](),
success: @escaping(Data, Int) -> (),
failure: @escaping(CustomError) -> ()) {
debugPrint("NetworkManager is calling endpoint: \(url)")
NetworkManager.alamofireManager.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers).validate().response { response in
guard let status = response.response?.statusCode, let data = response.data else {
if let error = response.error {
debugPrint("Error when calling endpoint \(url)")
failure(.unknownError(message: error.localizedDescription))
}
return
}
debugPrint("HTTP Status received: \(status)")
success(data, status)
}
} else {
failure(.noNetworkConnection)
}
}
请随意修改您的自定义错误或任何您喜欢的失败处理程序。
当然,您需要序列化响应。如果使用Alamofire库,我建议使用
class NetworkManager {
static let shared = NetworkManager()
static let alamofireManager: SessionManager = {
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.timeoutIntervalForRequest = TimeInterval(_TIMEOUT)
sessionConfiguration.timeoutIntervalForResource = TimeInterval(_TIMEOUT)
return Alamofire.SessionManager(configuration: sessionConfiguration)
}()
func performRequest(url: String,
method: HTTPMethod = .get,
parameters: [String: Any] = [String: Any](),
encoding: ParameterEncoding = URLEncoding.default,
contentType: String? = nil,
headers: HTTPHeaders = [String: String](),
success: @escaping(Data, Int) -> (),
failure: @escaping(CustomError) -> ()) {
debugPrint("NetworkManager is calling endpoint: \(url)")
NetworkManager.alamofireManager.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers).validate().response { response in
guard let status = response.response?.statusCode, let data = response.data else {
if let error = response.error {
debugPrint("Error when calling endpoint \(url)")
failure(.unknownError(message: error.localizedDescription))
}
return
}
debugPrint("HTTP Status received: \(status)")
success(data, status)
}
} else {
failure(.noNetworkConnection)
}
}
请随意修改您的自定义错误或任何您喜欢的失败处理程序。
当然,您需要序列化响应。为Alamofire请求创建一个基类,如下所示:
现在,您可以从任何位置调用此配置文件服务的doLogin方法,或者您可以创建更多类似于层的模型类并从模型类调用此服务,或者您可以像这样直接调用:
为Alamofire请求创建一个基类,如下所示:
现在,您可以从任何位置调用此配置文件服务的doLogin方法,或者您可以创建更多类似于层的模型类并从模型类调用此服务,或者您可以像这样直接调用:
切勿将视图和/或视图控制器传递给NetworkManager类。
假设您有这样一个NetworkManager类
open class NetworkHelper {
class var sharedManager: NetworkHelper {
struct Static{
static let instance: NetworkHelper = NetworkHelper()
}
return Static.instance
}
func request(_ method: HTTPMethod, _ URLString: String, parameters: [String : AnyObject]? = [:], headers: [String : String]? = [:], completion:@escaping (Any?) -> Void, failure: @escaping (Error?) -> Void) {
let URL = "BASE_PATH" + "URLString"
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
switch response.result {
case .success:
completion(response.result.value!)
case .failure(let error):
failure(error)
guard error.localizedDescription == JSON_COULDNOT_SERIALISED else {
return
}
}
}
}
}
现在创建一个从UIViewController继承的BaseViewController,并用必要的参数编写API调用。
例如,在一个API调用中,您只需要userID,因为param其他所有的都是静态的
不,您应该继承那些需要相同API调用且不想再次编写代码的ViewController
class FirstChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 123)
}
}
class SecondChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 13)
}
}
class ThirdChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 3)
}
}
请看,我没有在FirstChildViewController、SecondChildViewController、ThirdChildViewController中编写API代码,但它们仍然可以使用不同的参数进行相同的API调用。永远不要将视图和/或视图控制器传递给NetworkManager类。
假设您有这样一个NetworkManager类
open class NetworkHelper {
class var sharedManager: NetworkHelper {
struct Static{
static let instance: NetworkHelper = NetworkHelper()
}
return Static.instance
}
func request(_ method: HTTPMethod, _ URLString: String, parameters: [String : AnyObject]? = [:], headers: [String : String]? = [:], completion:@escaping (Any?) -> Void, failure: @escaping (Error?) -> Void) {
let URL = "BASE_PATH" + "URLString"
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
switch response.result {
case .success:
completion(response.result.value!)
case .failure(let error):
failure(error)
guard error.localizedDescription == JSON_COULDNOT_SERIALISED else {
return
}
}
}
}
}
现在创建一个从UIViewController继承的BaseViewController,并用必要的参数编写API调用。
例如,在一个API调用中,您只需要userID,因为param其他所有的都是静态的
不,您应该继承那些需要相同API调用且不想再次编写代码的ViewController
class FirstChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 123)
}
}
class SecondChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 13)
}
}
class ThirdChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 3)
}
}
请看,我没有在FirstChildViewController、SecondChildViewController、ThirdChildViewController中编写API代码,但它们仍然可以使用不同的参数进行相同的API调用