干货!Swift/OC高效管理API接口
2017-12-06 本文已影响198人
66b6d3e5fc98
Swift——enum管理模式
1,API接口
import Foundation
enum My_API {
case t新闻列表(page:Int,type:Int,processID:String)
case t书本列表(q:String)
}
2,各项值配置
//MARK:--- mainURL ----------
extension My_API {
var mainURLValue:String {
switch self {
case .t新闻列表(_ , _, _):
return "http://admin.militaryapp.china.com"
case .t书本列表(_):
return "https://api.douban.com"
}
}
}
//MARK:--- pathURLString ----------
extension My_API {
var pathValue:String {
switch self {
case .t新闻列表(_ , _, _):
return "/News/NewsServlet.do"
case .t书本列表(_):
return "/v2/book/search"
}
}
}
//MARK:--- parames ----------
extension My_API {
var paramesValue:[String:Any] {
switch self {
case .t新闻列表(let page, let type, let processID):
return ["page":page,"type":type,"processID":processID,"page-size":20]
case .t书本列表(let q):
return ["q":q]
}
}
}
//MARK:--- heard ----------
extension My_API {
var headerValue:[String:String] {
switch self {
case .t新闻列表(_,_,_):
return [:]
case .t书本列表(_):
return [:]
}
}
}
//MARK:--- encoding ----------
extension My_API {
var encodingValue: ParameterEncoding {
switch self {
case .t新闻列表(_, _, _):
return URLEncoding.default
case .t书本列表(_):
return JSONEncoding(options: [])
}
}
}
//MARK:--- HTTPMethod ----------
import Alamofire
extension My_API {
var methodValue: HTTPMethod {
switch self {
case .t新闻列表(_ , _, _):
return .get
case .t书本列表(_):
return .post
}
}
}
3,请求
typealias my_apiBlock = (_ isOk: Bool, _ data: Any, _ error: String) -> Void
//MARK:--- 上传 ----------
extension My_API {
func upload<T: My_JsonModel>(_ model: T.Type, block:((Bool,Any,String) -> Void)? = nil, progressBlock:cd_netProgressBlock? = nil) {
}
}
//MARK:--- 请求 ----------
extension My_API {
func request<T: My_JsonModel>(_ model: T.Type,
objType:My_APIObjectType = .tObject,
block:my_apiBlock? = nil)
{
CD_Alamofire.cd_request(mainURLValue+pathValue, method: methodValue, parameters: paramesValue, encoding: encodingValue, headers: headerValue) { (isOk, res, error) in
print("\(self)(\(self.mainURLValue+self.pathValue))==>\(JSON(res!))")//统一打印
My_API.my_ApiBlock(model, objType: objType, data: (isOk,res,error),block:block)
}
}
}
4,数据处理 + 转模型(泛型整合)
转模型框架SwiftyJSON、HandyJSON各有各的优势
本例使用SwiftyJSON,因为SwiftyJSON需要自定义协议泛型化,当初趟过坑。
import SwiftyJSON
//MARK:--- 通用模型 ----------
struct M_MyCommon {
//媒体上传 - 返回媒体地址
var media_url = ""
var media_img = ""
}
extension M_MyCommon:My_JsonModel {
init(_ json: JSON) {
if json.isEmpty{return}
media_url = json["url"].stringValue
media_img = json["media_img_url"].stringValue
}
}
//MARK:--- Json 数据 与后台的约定和错误处理----------
let My_Net_Code = "code"
let My_Net_Msg = "msg"
let My_Net_Data = "data"
//--- 数据初步处理
enum My_APIObjectType {
case tObject
case tArray
}
public protocol My_JsonModel {
//所有的转模型通过遵循 My_JsonModel 协议
init()
init(_ json:JSON)
}
//MARK:--- 数据处理 + 转模型 ----------
extension My_API {
static func my_ApiBlock<T: My_JsonModel>(_ model: T.Type, objType:My_APIObjectType, data:( isOk:Bool, response:Any?, error:String?), block:my_apiBlock? = nil) {
switch objType {
case .tObject:
My_API.map_Object(model, data:data, haveCode:true, block: block)
default:
My_API.map_Array(model, data:data, haveCode:true, block: block)
}
}
///SwiftyJSON Json->Model
static func map_FromJSON<T: My_JsonModel>(_ jsonData:JSON, classType: T.Type) -> T? {
return T(jsonData)
}
static func map_Array<T: My_JsonModel>(_ type: T.Type, data:( isOk:Bool, response:Any?, error:String?), haveCode:Bool = true, block:((Bool,[T],String)->Void)? = nil){
/*
if data.isOk {
let json = JSON(data.response!)
var array:[JSON] = []
if haveCode {
guard json[My_Net_Code].stringValue == My_NetCodeError.t成功.rawValue else{
let message = (My_NetCodeError(rawValue: json[My_Net_Code].stringValue) ?? .tError).stringValue
block?(false,[],message)
if json[My_Net_Code].stringValue == My_NetCodeError.t需要登录.rawValue {
My_API.needLogin()
}
return
}
guard let arr:[JSON] = json[My_Net_Data].array else{
block?(true,[],cd_Localization(My_NetCodeError.t没有数据.rawValue))
return
}
array = arr
}else{
array = json.arrayValue
}
var objects = [T]()
if array.count > 0 {
for object in array {//转模型
if let obj = My_API.map_FromJSON(object, classType:type) {
objects.append(obj)
}
}
block?(true,objects,"")
} else {
block?(true,[],cd_Localization(My_NetCodeError.t没有数据.rawValue))
}
}else{
block?(false,[],data.error!)
}*/
}
static func map_Object<T: My_JsonModel>(_ type: T.Type, data:( isOk:Bool, response:Any?, error:String?), haveCode:Bool = true, block:((Bool,T,String)->Void)? = nil){
//省略一堆处理(同上)
}
6
//登录失效处理
/*
static func needLogin() {
SP_User.shared.needLogin()
}*/
}
5,使用示例
My_API.t新闻列表(page: 1, type: 1, processID: "getNewsList")
.request(M_MyCommon.self, objType: .tArray)
{ [weak self](isOk, res, error) in
}
Swift——Moya管理(不太推荐,没必要)
1,各项值配置()
import Moya
extension My_API: TargetType {
var baseURL: URL {
switch self {
case .t新闻列表(_ , _, _):
return URL(string: "http://admin.militaryapp.china.com/")!
case .t书本列表(_):
return URL(string: "https://api.douban.com/")!
}
}
var path: String {
switch self {
case .t新闻列表(_ , _, _):
return "News/NewsServlet.do"
case .t书本列表(_):
return "v2/book/search"
}
}
var method: Moya.Method {
switch self {
case .t新闻列表(_ , _, _):
return .get
case .t书本列表(_):
return .post
}
}
var parameters: [String: Any] {
switch self {
case .t新闻列表(let page, let type, let processID):
return ["page":page,"type":type,"processID":processID]
case .t书本列表(let q):
return ["q":q]
}
}
var parameterEncoding: ParameterEncoding {
switch self {
case .t新闻列表(_, _, _):
return URLEncoding.default
case .t书本列表(_):
return JSONEncoding(options: [])
}
}
var sampleData: Data {
return "".data(using: String.Encoding.utf8)!
}
var task: Task {
return .requestParameters(parameters: parameters, encoding: parameterEncoding)
}
var headers: [String : String]? {
switch self {
case .t新闻列表(_,_,_):
return [:]
case .t书本列表(_):
return [:]
}
}
}
2,使用示例(配合RxSwift)
myApiProvider.rx
.request(.t新闻列表(page: 1, type: 1, processID: "getNewsList"))
.mapJSON()//可扩展RxSwift Single 自定义mapJSON,再配合SwiftyJSON/HandyJSON进一步做数据处理
.subscribe(onSuccess: { (res) in
print(JSON(res))
}) { (error) in
}
.disposed(by:disposeBag)
Swift——其他管理模式
//管理方法很多,个人觉得不利用第三方 enum 管理较轻便
OC——常量+工厂管理(拒绝使用宏)
1,常量管理API接口地址
@interface My_URLs : NSObject
#pragma mark ----- 配置 (拒绝使用宏)-----
/** pageSize 每页条数 */
extern NSString* const pageSize;
/** code 数据反馈标识 */
extern NSString* const code;
/** msg 数据反馈信息 */
extern NSString* const msg;
/** data 数据内容 */
extern NSString* const data;
/** 根地址*/
extern NSString* const main_URL;
/** 获取新闻列表*/
extern NSString* const getNewsServlet;
/** 获取书本列表*/
extern NSString* const getBooks;
@end
#import "My_URLs.h"
@implementation My_URLs
NSString * const pageSize = @"20";
NSString * const code = @"status";
NSString * const msg = @"msg";
NSString * const data = @"data";
NSString * const main_URL = @"";
NSString * const getNewsServlet = @"http://admin.militaryapp.china.com/News/NewsServlet.do";
NSString * const getBooks = @"https://api.douban.com/v2/book/search";
@end
2,工厂化
//block:(void (^)(BOOL isOk, NSDictionary * data, NSString* msg))block
typedef void (^DataBlock)(BOOL isOk, NSDictionary * data, NSString* msg);
@interface My_API : NSObject
+ (void) getNewsListWithParams:(NSDictionary*)params block:(DataBlock)block;
+ (void) getBooksWithParams:(NSDictionary*)params block:(DataBlock)block;
@end
#import "My_API.h"
#import "CD_AF.h"
#import "My_URLs.h"
#import <AFNetworking/AFNetworking.h>
#define My_APIS(string, args...) [NSString stringWithFormat:string, args]
@implementation My_API
+ (void) getNewsListWithParams:(NSDictionary*)params block:(DataBlock)block {
[CD_AF.shared setContentTypes:@"text/html"];
__block NSMutableDictionary * dic = [NSMutableDictionary dictionary];
[dic setValue:pageSize forKey:@"pageSize"];
[params enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[dic setValue:obj forKey:key];
}];
[CD_AF.shared requestWithMethod:tGet
urlString:My_APIS(@"%@%@",main_URL,getNewsServlet)
parameters:dic
withRequestBlock:^(id result, NSError *error) {
if (!error) {
[My_API makeArray:result block:block];
}else{
}
}];
};
+ (void) getBooksWithParams:(NSDictionary*)params block:(DataBlock)block {
[CD_AF.shared setContentTypes:@"application/json"];
__block NSMutableDictionary * dic = [NSMutableDictionary dictionary];
[params enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[dic setValue:obj forKey:key];
}];
[CD_AF.shared requestWithMethod:tGet
urlString:My_APIS(@"%@%@",main_URL,getBooks)
parameters:dic
withRequestBlock:^(id result, NSError *error) {
if (!error) {
[My_API makeArray:result block:block];
}else{
}
}];
};
/**数据处理*/
+ (void) makeObj:(id)result block:(DataBlock)block {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@",dic);
if ([dic[code] isEqualToString:@"0"]) {
block(YES,dic[data],@"");
}else{
block(NO,nil,dic[msg]);
}
}
+ (void) makeArray:(id)result block:(DataBlock)block {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingMutableLeaves error:nil];
//block(YES,dic[@"books"],@"");
if ([dic[code] isEqualToString:@"success"]) {
block(YES,dic[data],@"");
}else{
block(NO,nil,dic[msg]);
}
}
@end