RestApiManager
- 从端点解耦 URLSession 逻辑
- 自动映射响应对象
- 响应类型:对象、数组、字符串、自定义响应序列化程序
- 轻松处理多部分请求
- 在控制台中打印酷请求和响应
- 自动显示加载指示器
- 自动显示错误警告
- 可以为每个请求设置唯一的错误类型(ResultWithET
,其中 T - 响应类型,ET - 错误类型)
CocoaPods
将以下行添加到您的 Podfile 中
pod 'RestApiManager'
使用
实例
使用 RestApiManager,您可以简单地创建 URLSessionRAMDIContainer,并将其注入到 RestApiManager 实例中。在 URLSessionRAMDIContainer 中,您可以自定义(错误类型、urlSession、jsonDecoder、restApiAlert、restApiActivityIndicator、printRequestInfo)属性。
let urlSessionRAMDIContainer = URLSessionRAMDIContainer(errorType: ExampleRestApiError.self, printRequestInfo: true)
let restApiManager: RestApiManager = URLSessionRestApiManager(urlSessionRAMDIContainer: urlSessionRAMDIContainer)
创建方法
要创建API方法,您应实现RestApiMethod和ParametersProtocol协议。
enum QuestionsRestApiMethods: RestApiMethod {
// Method
case getQuestions(QuestionsRestApiParameters)
// URL
private static let getQuestionsUrl = "questions"
// RestApiData
var data: RestApiData {
switch self {
case .getQuestions(let parameters):
return RestApiData(url: RestApiConstants.baseURL + QuestionsRestApiMethods.getQuestionsUrl,
httpMethod: .get,
parameters: parameters,
keyPath: RestApiConstants.items)
}
}
}
struct QuestionsRestApiParameters: ParametersProtocol {
let order = "desc"
let sort = "votes"
let site = "stackoverflow"
var parametersValue: Parameters {
let parameters: [String: Any] = [
RestApiConstants.order: order,
RestApiConstants.sort: sort,
RestApiConstants.site: site
]
return parameters
}
}
调用
要创建API调用,您应创建RestApiMethod实例。然后使用RestApiManager的一些现有的“调用”方法发送请求。
创建RestApiMethod实例
private let questionsParameters = QuestionsRestApiParameters()
private let getQuestionsMethod: QuestionsRestApiMethods = .getQuestions(questionsParameters)
数组响应调用
func simpleCall() {
restApiManager.call(method: getQuestionsMethod) { (result: Result<[StackoverflowItemModel]>) in
switch result {
case .success(let obj):
// some action with success result
case .failure(let error):
// some action with failure result
}
}
}
带有自动显示指示器和错误警报的调用
func simpleCallWithIndicatorAndErrorAlert() {
restApiManager.call(method: getQuestionsMethod,
indicator: true,
errorAlert: true)
{ (result: Result<[StackoverflowItemModel]>) in
switch result {
case .success(let obj):
// some action with success result
case .failure(let error):
// some action with failure result
}
}
}
错误处理
对于错误处理,您可以使用我们的DefaultRestApiError。或者创建您自己的错误处理实现。为此,您应在您的类中实现RestApiError协议,并将其注入URLSessionRAMDIContainer。
在RestApiError协议的"handle"方法中,您应实现错误解析方法,它将返回您的可选类实例。如果您返回nil,这意味着您的请求将返回成功响应。
final class ExampleRestApiError: RestApiError {
// MARK: - Properties
var code: Int
var details: String
// MARK: - Inits
convenience init() {
self.init(code: 0)
}
convenience init(error: Error) {
let nsError = error as NSError
self.init(code: nsError.code, details: nsError.localizedDescription)
}
convenience init(code: Int) {
self.init(code: code, details: "")
}
init(code: Int, details: String) {
self.code = code
self.details = details
}
// MARK: - Handle
/// method for handle error by response, if parse to Error success, method will be return Error
///
/// - Parameters:
/// - error: Error?
/// - urlResponse: URLResponse?
/// - data: Data? for parsing to Error
/// - Returns: ExampleRestApiError
static func handle(error: Error?, urlResponse: URLResponse?, data: Data?) -> ExampleRestApiError? {
if let error = error {
return ExampleRestApiError(error: error)
} else if let data = data {
guard !data.isEmpty else {
return nil
}
do {
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject],
let code = json[RestApiConstants.code] as? Int,
let message = json[RestApiConstants.message] as? String {
let error = ExampleRestApiError(code: code, details: message)
return error
} else {
return nil
}
} catch let error as NSError {
return ExampleRestApiError(error: error)
}
} else {
return ExampleRestApiError.unknown
}
}
}
let urlSessionRAMDIContainer = URLSessionRAMDIContainer(errorType: ExampleRestApiError.self)
let restApiManager: RestApiManager = URLSessionRestApiManager(urlSessionRAMDIContainer: urlSessionRAMDIContainer)
自动显示错误警报
要自动显示错误警报,您应在“调用”方法中将“指示器”属性设置为“true”。您可以使用我们的DefaultRestApiAlert类来显示警报。或者创建您自己的警报实现。为此,您应在您的类中实现RestApiAlert协议,并将其注入URLSessionRAMDIContainer。
public class ExampleRestApiAlert: RestApiAlert {
/// init
public init() {}
/// show
///
/// - Parameter error: RestApiError
public func show(error: RestApiError) {
show(title: "Error", message: error.details, completion: nil)
}
/// show
///
/// - Parameters:
/// - title: title of UIAlertController
/// - message: message of UIAlertController
/// - completion: completion of UIAlertController
public func show(title: String, message: String, completion: (() -> Void)?) {
guard let rootViewController = UIApplication.presentationViewController else {
return
}
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default, handler: { [unowned self] _ in
completion?()
})
alert.addAction(okAction)
rootViewController.present(alert, animated: true, completion: nil)
}
}
自动显示加载指示器
要自动显示加载指示器,您应在“调用”方法中将“指示器”属性设置为“true”。您可以使用我们的DefaultRestApiActivityIndicator类来显示指示器。或者创建您自己的指示器视图实现。为此,您应在您的类中实现RestApiActivityIndicator协议,并将其注入URLSessionRAMDIContainer。
func show()
func show(onView view: UIView)
func hide()
示例目标
您可以在示例目标中检查RestApiManager的更多功能。
许可协议
RestApiManager采用MIT许可协议发布。更多信息请见许可协议。