美文网首页
干货!Swift/OC高效管理API接口

干货!Swift/OC高效管理API接口

作者: 66b6d3e5fc98 | 来源:发表于2017-12-06 18:04 被阅读198次

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

相关文章

  • 干货!Swift/OC高效管理API接口

    Swift——enum管理模式 1,API接口 2,各项值配置 3,请求 4,数据处理 + 转模型(泛型整合) 转...

  • OC与Swift混编

    OC引用Swift 在混合项目中Swift代码默认使用module管理,这时想要OC引用Swift需要把Swift...

  • Swift | 函数的闭包参数标签被忽略的问题

    先看看 Swift 的 UIView 动画: 接口: 调用: 同样是 UIView 动画,看看别人 OC: 接口:...

  • [Swift2.0系列]API可用性检查(译)

    Swift2.0:API可用性检查 Swift安全至上。除了Swift2.0引入的API(应用程序编程接口)可用性...

  • Swift5 引导页

    Swift5.x版本,ABI(应用程序二进制接口)终于稳定,也是时候从OC转Swift了? 熟悉的OC框架,有的可...

  • YApi 本地部署

    描述 YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可...

  • Swift-Basic Learning

    1. Siwft与OC混编 OC调用SWIfFT SWIfFT调用OC 2. Swift用cocoapods管理...

  • Swift 小仿微博列表

    前言 鉴于目前Swift的ABI(应用程序二进制接口)、API(应用程序编程接口) 基本稳定,对于Swift的...

  • OC和Swift的区别

    oc和swift字符串的区别和优缺点。在oc中字符串是对象,在swift中是结构体。他们的使用最终都是调api,所...

  • iOS架构篇-3 网络接口封装

    iOS架构篇-3 网络接口封装 关键字:iOS,网络接口封装,Alamofire,swift 网络接口API通常都...

网友评论

      本文标题:干货!Swift/OC高效管理API接口

      本文链接:https://www.haomeiwen.com/subject/kwvqixtx.html