干货!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,数据处理 + 转模型(泛型整合)

转模型框架SwiftyJSONHandyJSON各有各的优势
本例使用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
上一篇下一篇

猜你喜欢

热点阅读