【发布时间】:2019-04-06 10:58:57
【问题描述】:
每个 API 在响应中都有三个参数。
-
Code:表示 API 是成功还是失败(1 或 0) -
Message:一个字符串 -
Data:可以是对象或单个对象的Array。
我已经创建了基础模型。
struct ResponseBase<T:Codable> : Codable {
let code : String?
let data : [T]
let message : String?
enum CodingKeys: String, CodingKey {
case code = "Code"
case data = "Data"
case message = "Message"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
code = try values.decodeIfPresent(String.self, forKey: .code)
data = try values.decodeIfPresent([T].self, forKey: .data)
message = try values.decodeIfPresent(String.self, forKey: .message)
}
}
struct SocialWarmer : Codable {
let createdDate : String?
let lookUpId : String?
let lookupKey : String?
let lookupValue : String?
let parentId : String?
let statusFlag : String?
let type : String?
let updatedDate : String?
enum CodingKeys: String, CodingKey {
case createdDate = "CreatedDate"
case lookUpId = "LookUpId"
case lookupKey = "LookupKey"
case lookupValue = "LookupValue"
case parentId = "ParentId"
case statusFlag = "StatusFlag"
case type = "Type"
case updatedDate = "UpdatedDate"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
createdDate = try values.decodeIfPresent(String.self, forKey: .createdDate)
lookUpId = try values.decodeIfPresent(String.self, forKey: .lookUpId)
lookupKey = try values.decodeIfPresent(String.self, forKey: .lookupKey)
lookupValue = try values.decodeIfPresent(String.self, forKey: .lookupValue)
parentId = try values.decodeIfPresent(String.self, forKey: .parentId)
statusFlag = try values.decodeIfPresent(String.self, forKey: .statusFlag)
type = try values.decodeIfPresent(String.self, forKey: .type)
updatedDate = try values.decodeIfPresent(String.self, forKey: .updatedDate)
}
}
以下是 API 请求代码。
class BaseApiClient {
static let `default` = BaseApiClient()
private init() {
}
func fetch<model:Codable>(request:APIRouter,decoder : JSONDecoder = JSONDecoder() ,onSuccess: @escaping ([model]) -> Void) {
if Connectivity.isReachable {
(UIApplication.shared.delegate as! AppDelegate).addProgressView()
Alamofire.request(request).responseJSON { (response) in
switch response.result {
case .success( let apiResponse) :
DispatchQueue.main.async {
(UIApplication.shared.delegate as! AppDelegate).hideProgrssVoew()
}
if let responseData = apiResponse as? [String:Any] , let status = responseData["Code"] as? String , status == "SUCCESS" {
do {
let responseModel = try decoder.decode(ResponseBase<model>.self, from: response.data!)
onSuccess(responseModel.data!)
}
catch let error as NSError {
print("failed reason : \(error.localizedDescription)")
}
print(model.Type.self)
print(model.self)
}
else {
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Erorr", message: "Service not Avilabel" ,okclick: nil)
}
case .failure(let error) :
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Erorr", message: error.localizedDescription, okclick: nil)
}
}
}
else {
(UIApplication.shared.delegate as! AppDelegate).hideProgrssVoew()
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Error", message: "connnection not avilabel", okclick: nil)
}
}
}
以下是调用 API 的代码。
BaseApiClient.default.fetch(request: APIRouter.GetSocialWarmerType) { (response: [SocialWarmer]) in
print(response)
}
但如果数据是单个对象,则此模型和 API 方法将不起作用。 我想要实现的是创建单个模型并在 API 方法中进行适当的更改,以解析对象数组和单个对象。
【问题讨论】:
-
无关,那些
init(from:)方法在您的Codable类型中是不必要的。 -
我还建议只使用 Alamofire
response而不是responseJSON。如果你要再次解析它,那么让 Alamofire 解析你的 JSON 是没有意义的。 -
您说
Code将“指示API 是成功还是失败(1 或0)”。但是您随后将其定义为String?。似乎它是1 还是0,即应该是Int。我也不清楚ResponseBase的所有三种类型都是可选的概念吗?你不能保证至少Code总是在那里吗? -
最后,我建议泛型只使用
Decodable(不是Codable)的约束。在实践中,这可能不是什么大问题,但ResponseBase并不真正关心响应中的类型是否可以同时编码和解码。它只关心它是否可以被解码。