美文网首页iOS/macOS/watchOSiOS技术资料
干货!Alamofire/AFNetWorking 使用及二次封

干货!Alamofire/AFNetWorking 使用及二次封

作者: 66b6d3e5fc98 | 来源:发表于2017-03-16 09:51 被阅读1468次

    Swift—— Alamofire

    1,一个单例 + 工厂方法
    import Foundation
    import Alamofire
    
    class CD_Alamofire {
        open static let shared: CD_Alamofire = CD_Alamofire()
        fileprivate let _manager = SessionManager.default
        
        let CD_NetStatusNotifyName = "CD_NetworkReachabilityStatus"
        ///取消上传
        var cd_uploadCancel = false
        ///当前网络状态
        var cd_netStatusNow:CD_NetworkReachabilityStatus = .tNnknown {
            didSet{
                NotificationCenter.default.post(name: NSNotification.Name(rawValue:CD_NetStatusNotifyName), object: cd_netStatusNow, userInfo: [:])
            }
        }
        fileprivate var openNetStatus:Bool = false
    }
    //MARK:--- 请求,上传,下载 ----------
    /// 网络请求回调闭包 success:是否成功 result:数据 progress:请求进度 error:错误信息
    typealias cd_netComBlock = (_ success: Bool, _ result: Any?, _ error: String?) -> Void
    typealias cd_netProgressBlock = (_ progress:Progress?) -> Void
    
    extension CD_Alamofire {
        ///请求
        class func cd_request(
            _ url: String,
            method: HTTPMethod = .get,
            parameters:[String:String] = [:],
            encoding: ParameterEncoding = URLEncoding.default,
            headers: HTTPHeaders? = nil,
            block: cd_netComBlock? = nil) {
            guard !url.isEmpty else {
                block?(false,"","空地址")
                return
            }
            CD_Alamofire.shared._manager.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers).responseJSON { response in
                CD_Alamofire.disposeResponse(response, block:block)
            }
        }
        ///上传
        class func cd_upload(
            _ url:String,
            param:[String:String] = [:],
            uploadParams:[CD_UploadParam],
            headers: HTTPHeaders? = nil,
            progressBlock: cd_netProgressBlock? = nil,
            block: cd_netComBlock? = nil) {
            guard !url.isEmpty else {
                block?(false,"","空地址")
                return
            }
            CD_Alamofire.shared.cd_uploadCancel = false
            CD_Alamofire.shared._manager.upload(multipartFormData: { (formData) in
                for item in uploadParams {
                    switch (item.type) {
                    case .tData:
                        formData.append(item.fileData, withName: item.serverName, fileName: item.filename, mimeType: item.mimeType)
                    case .tFileURL:
                        if let fileUrl = item.fileURL {
                            formData.append(fileUrl, withName: item.serverName, fileName: item.filename, mimeType: item.mimeType)
                        }
                    }
                }
                for item in param {
                    let dat:Data = item.value.data(using: String.Encoding.utf8) ?? Data()
                    formData.append(dat, withName: item.key)
                }
            }, to: url, headers:headers, encodingCompletion: { (encodingResult) in
                switch encodingResult {
                case .success(let uploads, _, _):
                    if CD_Alamofire.shared.cd_uploadCancel {
                        uploads.cancel()
                    }
                    uploads.uploadProgress(closure: { (progress) in
                        progressBlock?(progress)
                    }).responseJSON { response in
                        CD_Alamofire.disposeResponse(response, block:block)
                    }
                case .failure(let error):
                    block?(false,"",cd_returnNSError(error))
                }
            })
        }
        ///下载
        class func cd_downLoad(
            _ url:String,
            param:[String:Any],
            progressBlock: cd_netProgressBlock? = nil,
            block: cd_netComBlock? = nil) {
            
        }
        ///数据处理
        fileprivate class func disposeResponse(_ response:DataResponse<Any>, block:cd_netComBlock? = nil) {
            var error = ""
            var isOk = false
            switch response.result {
            case .success(let json):
                if (response.result.value != nil) {
                    isOk = true
                    error = ""
                } else{
                    isOk = false
                    error = CD_ErrorType.noData.stringValue
                }
                block?(isOk,json,error)
            case .failure(let error):
                isOk = false
                block?(isOk,"",cd_returnNSError(error))
            }
        }
    }
    //MARK:--- 网络监测 建议在 AppDelegate 中开启,响应存在不及时----------
    fileprivate let CD_NetworkManager = NetworkReachabilityManager(host: "www.baidu.com")
    extension CD_Alamofire {
        public enum CD_NetworkReachabilityStatus {
            case tNotReachable
            case tNnknown
            case tEthernetOrWiFi
            case tWWAN
        }
        ///开启网络监测
        class func cd_OpenNetStatus() {
            guard !CD_Alamofire.shared.openNetStatus else {
                CD_Alamofire.shared.cd_netStatusNow = CD_Alamofire.shared.cd_netStatusNow
                return
            }
            CD_Alamofire.shared.openNetStatus = true
            //首次进入有网络会响应,但没网络不响应
            CD_NetworkManager!.listener = { status in
                switch status {
                case .notReachable:
                    CD_Alamofire.shared.cd_netStatusNow = .tNotReachable
                case .unknown:
                    CD_Alamofire.shared.cd_netStatusNow = .tNnknown
                case .reachable(.ethernetOrWiFi):
                    CD_Alamofire.shared.cd_netStatusNow = .tEthernetOrWiFi
                case .reachable(.wwan):
                    CD_Alamofire.shared.cd_netStatusNow = .tWWAN
                }
            }
            CD_NetworkManager!.startListening()
        }
    }
    
    //MARK:--- SSL认证 ([来自航歌](http://www.hangge.com/blog/cache/detail_991.html))-----------------------------
    extension CD_Alamofire {
        //存储认证相关信息
        struct CD_IdentityAndTrust {
            var identityRef:SecIdentity
            var trust:SecTrust
            var certArray:AnyObject
        }
        
        func cd_SSL(_ hosts:[String], p12:(name:String, pwd:String)) {
            let selfSignedHosts = hosts//["192.168.1.112", "www.hangge.com"]
            _manager.delegate.sessionDidReceiveChallenge = { session, challenge in
                //认证服务器(这里不使用服务器证书认证,只需地址是我们定义的几个地址即可信任)
                if challenge.protectionSpace.authenticationMethod
                    == NSURLAuthenticationMethodServerTrust
                    && selfSignedHosts.contains(challenge.protectionSpace.host)
                {
                    print("服务器认证!")
                    let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
                    return (.useCredential, credential)
                }
                    //认证客户端证书
                else if challenge.protectionSpace.authenticationMethod
                    == NSURLAuthenticationMethodClientCertificate
                {
                    print("客户端证书认证!")
                    //获取客户端证书相关信息
                    let identityAndTrust:CD_IdentityAndTrust = self.extractIdentity(p12);
                    let urlCredential:URLCredential = URLCredential(
                        identity: identityAndTrust.identityRef,
                        certificates: identityAndTrust.certArray as? [AnyObject],
                        persistence: URLCredential.Persistence.forSession);
                    
                    return (.useCredential, urlCredential);
                }
                    // 其它情况(不接受认证)
                else
                {
                    print("其它情况(不接受认证)")
                    return (.cancelAuthenticationChallenge, nil)
                }
            }
        }
        //MARK:--- 双向认证 -----------------------------
        func cd_SSL(_ cerName:String ,p12:(name:String, pwd:String)) {
            
            _manager.delegate.sessionDidReceiveChallenge = { (session, challenge) in
                //认证服务器证书
                if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
                {
                    print("服务端证书认证!")
                    let serverTrust:SecTrust = challenge.protectionSpace.serverTrust!
                    let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0)!
                    let remoteCertificateData
                        = CFBridgingRetain(SecCertificateCopyData(certificate))!
                    //证书目录
                    let cerPath = Bundle.main.path(forResource: cerName, ofType: "cer")!
                    let cerUrl = URL(fileURLWithPath:cerPath)
                    let localCertificateData = try! Data(contentsOf: cerUrl)
                    if (remoteCertificateData.isEqual(localCertificateData) == true) {
                        let credential = URLCredential(trust: serverTrust)
                        challenge.sender?.use(credential, for: challenge)
                        return (URLSession.AuthChallengeDisposition.useCredential,
                                URLCredential(trust: challenge.protectionSpace.serverTrust!))
                    }else {
                        return (.cancelAuthenticationChallenge, nil)
                    }
                }
                    //认证客户端证书
                else if challenge.protectionSpace.authenticationMethod
                    == NSURLAuthenticationMethodClientCertificate
                {
                    print("客户端证书认证!")
                    //获取客户端证书相关信息
                    let identityAndTrust:CD_IdentityAndTrust = self.extractIdentity(p12);
                    
                    let urlCredential:URLCredential = URLCredential(
                        identity: identityAndTrust.identityRef,
                        certificates: identityAndTrust.certArray as? [AnyObject],
                        persistence: URLCredential.Persistence.forSession);
                    
                    return (.useCredential, urlCredential);
                }
                    // 其它情况(不接受认证)
                else
                {
                    print("其它情况(不接受认证)")
                    return (.cancelAuthenticationChallenge, nil)
                }
            }
        }
        //MARK:--- 获取客户端证书相关信息 -----------------------------
        fileprivate func extractIdentity(_ p12:(name:String, pwd:String)) -> CD_IdentityAndTrust {
            
            var identityAndTrust:CD_IdentityAndTrust!
            var securityError:OSStatus = errSecSuccess
            //客户端证书 p12 文件目录
            let path: String = Bundle.main.path(forResource: p12.name, ofType: "p12")!
            let PKCS12Data = NSData(contentsOfFile:path)!
            let key : NSString = kSecImportExportPassphrase as NSString
            let options : NSDictionary = [key : p12.pwd] //客户端证书密码
            //create variable for holding security information
            //var privateKeyRef: SecKeyRef? = nil
            var items : CFArray?
            securityError = SecPKCS12Import(PKCS12Data, options, &items)
            if securityError == errSecSuccess {
                let certItems:CFArray = items as CFArray!;
                let certItemsArray:Array = certItems as Array
                let dict:AnyObject? = certItemsArray.first;
                if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {
                    // grab the identity
                    let identityPointer:AnyObject? = certEntry["identity"];
                    let secIdentityRef:SecIdentity = identityPointer as! SecIdentity!
                    //print("\(identityPointer)  :::: \(secIdentityRef)")
                    // grab the trust
                    let trustPointer:AnyObject? = certEntry["trust"]
                    let trustRef:SecTrust = trustPointer as! SecTrust
                    //print("\(trustPointer)  :::: \(trustRef)")
                    // grab the cert
                    let chainPointer:AnyObject? = certEntry["chain"]
                    identityAndTrust = CD_IdentityAndTrust(identityRef: secIdentityRef,
                                                           trust: trustRef, certArray:  chainPointer!)
                }
            }
            return identityAndTrust;
        }
    }
    
    2, CD_UploadParam
    enum CD_UploadParamType {
        case tData
        case tFileURL
    }
    struct CD_UploadParam {
        ///Data数据流
        var fileData = Data()
        ///文件的FileURL
        var fileURL:URL?
        ///服务器对应的参数名称
        var serverName = ""
        ///文件的名称(上传到服务器后,服务器保存的文件名)
        var filename = ""
        ///文件的MIME类型(image/png,image/jpg,application/octet-stream/video/mp4等)
        var mimeType = "image/png"
        ///文件类型
        var type:CD_UploadParamType = .tData
    }
    
    3,反馈编码
    //error = CD_ErrorType.noData.stringValue
    //block?(isOk,"",cd_returnNSError(error))
    enum CD_ErrorType:Int {
        case noData      = 10000000
        case nsurlErrorUnknown = -1
        ……
        var stringValue:String {
            switch self {
            case .nsurlErrorUnknown:                                 return cd_Localization("未知错误",from:"CD_ErrorType")
            case .nsurlErrorCancelled:                               return cd_Localization("取消了网址",from:"CD_ErrorType")
        ……
        }
    }
    //省略一堆反馈编码
    
    4,反馈编码国际化
    //省略一堆反馈编码国际化
    
    5,使用示例
            CD_Alamofire.cd_request("") { (isOk, data, error) in
                
            }
    

    OC—— AFNetWorking

    1,一个单例
    #import "CD_UploadParam.h"
    /**
     *  网络连接类型
     */
    typedef NS_ENUM(NSInteger) {
        tUnknown,
        tNotNet,
        tWWAN,
        tWiFi
    }CD_AFNetType;
    typedef NS_ENUM(NSInteger) {
        tGet,
        tPost,
        tPut,
    }CD_AFMethod;
    
    typedef void (^RequestResult)(id result, NSError * error);
    typedef void (^ProgressResult)(NSProgress * progress);
    
    @interface CD_AF : NSObject
    @property(nonatomic,strong) NSString *name;
    + (CD_AF*)shared;
    + (void)cd_print;
    
    
    #pragma mark --- 监测网络的可链接性
    /*
     netTypeBlock, 在需要监听网络链接状态改变时使用
     haveNet 在判断是否有网络链接时用
     */
    @property (nonatomic, weak) __block void (^netTypeBlock)(CD_AFNetType type);
    - (BOOL) haveNet;
    /** 请求头 Header*/
    @property(nonatomic,strong) NSDictionary * httpHeader;
    /** 最大并发数*/
    @property(nonatomic,assign) NSInteger maxOperationCount;
    /** 不设置会报 error 3840 (text/html) (application/json; charset=utf-8)(application/json)*/
    @property(nonatomic,strong) NSString * contentTypes;
    /** https:    SSL*/
    - (void)sslWithNone;
    - (void)sslWithPublicKey;
    - (void)sslWithCertificateFromPath:(NSString*)path;
    #pragma mark --- 发送请求
    /**
     *  发送请求
     *   method            请求类型
     *   urlString         请求的网址字符串
     *   parameters        请求的参数
     *   requestResult     请求成功/失败的回调
     */
    - (void)requestWithMethod:(CD_AFMethod)method
                    urlString:(NSString *)urlString
                   parameters:(id)parameters
             withRequestBlock:(RequestResult)requestResult;
    
    #pragma mark --- 上传图片
    /**
     *  上传图片
     *
     *   URLString         上传图片的网址字符串
     *   parameters        上传图片的参数
     *   uploadParam       上传图片的信息
     *   progress          上传进度的回调
     *   requestResult     上传成功/失败的回调
     */
    - (void)uploadWithURLString:(NSString *)urlString
                     parameters:(id)parameters
                    uploadParam:(NSArray <CD_UploadParam *> *)uploadParams
              withProgressBlock:(ProgressResult)progress
               withRequestBlock:(RequestResult)requestResult;
    
    #pragma mark --- 下载数据
    /**
     *  下载数据
     *
     *   URLString         下载数据的网址
     *   parameters        下载数据的参数
     *   progress          下载进度的回调
     *   requestResult     下载成功/失败的回调
     */
    - (void)downLoadWithURLString:(NSString *)urlString
                       parameters:(id)parameters
                withProgressBlock:(ProgressResult)progress
                 withRequestBlock:(RequestResult)requestResult;
    
    @end
    
    #import <AFNetworking/AFNetworking.h>
    
    static CD_AF* shared = nil;
    
    @interface CD_AF(){
        AFHTTPSessionManager * _manager;
        __block BOOL _hasReachability;
        __block CD_AFNetType _netState;
    }
    
    @end
    
    
    @implementation CD_AF
    #pragma mark ----- 单例 -----
    + (CD_AF*) shared
    {
        static dispatch_once_t once;
        dispatch_once(&once, ^{
            if (shared == nil) {
                shared = [[self alloc] init];
            }
        });
        return shared;
    }
    /**
     覆盖该方法主要确保当用户通过[[* alloc] init]创建对象时对象的唯一性,alloc方法会调用该方法,只不过zone参数默认为nil,因该类覆盖了allocWithZone方法,所以只能通过其父类分配内存,即[super allocWithZone:zone]
     */
    +(id)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t token;
        dispatch_once(&token, ^{
            if(shared == nil){
                shared = [super allocWithZone:zone];
            }
        });
        return shared;
    }
    //自定义初始化方法
    - (instancetype)init
    {
        self = [super init];
        if(self){
            [self makeManager];
        }
        return self;
    }
    //覆盖该方法主要确保当用户通过copy方法产生对象时对象的唯一性
    - (id)copy
    {
        return self;
    }
    //覆盖该方法主要确保当用户通过mutableCopy方法产生对象时对象的唯一性
    - (id)mutableCopy
    {
        return self;
    }
    //自定义描述信息,用于log详细打印
    - (NSString *)description
    {
        return [NSString stringWithFormat:@"memeory address:%p,property name:%@",self,self.name];
    }
    //测试
    + (void)cd_print {
        CD_AF *allocSingleton = [[CD_AF alloc] init];
        NSLog(@"allocSingleton:\n%@",allocSingleton);
        CD_AF *copySingleton = [allocSingleton copy];
        NSLog(@"copySingleton:\n%@",copySingleton);
        CD_AF *mutebleCopySingleton = [allocSingleton mutableCopy];
        NSLog(@"mutebleCopySingleton:\n%@",mutebleCopySingleton);
        CD_AF *defaultManagerSingleton =[CD_AF shared];
        NSLog(@"defaultManagerSingleton:\n%@",defaultManagerSingleton);
    }
    
    
    - (void)makeManager{
        _manager = [AFHTTPSessionManager manager];
        [_manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
        _manager.requestSerializer.timeoutInterval = 15.0;
        [_manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
        
        //支持Cookie
        _manager.requestSerializer.HTTPShouldHandleCookies = YES;
        //不设置会报-1016或者会有编码问题
        _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        //设置默认的ContentType
        [self setContentTypes:@"application/json"];
    }
    - (void) setContentTypes:(NSString *)contentTypes {
        //不设置会报 error 3840 (text/html) (application/json; charset=utf-8)(application/json)
        _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:contentTypes];
    }
    
    - (void)sslWithNone{
        _manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        //allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO//如果是需要验证自建证书,需要设置为YES
        [_manager.securityPolicy setAllowInvalidCertificates:YES];
        //validatesDomainName 是否需要验证域名,默认为YES;
        [_manager.securityPolicy setValidatesDomainName:NO];
    }
    - (void)sslWithPublicKey{
    }
    - (void)sslWithCertificateFromPath:(NSString*)path{
        // 2.设置证书模式
        NSString * cerPath = [[NSBundle mainBundle] pathForResource:path ofType:@"cer"];
        NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
        if (cerData == nil) {return;}
        _manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:cerData, nil]];
        //allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO//如果是需要验证自建证书,需要设置为YES
        [_manager.securityPolicy setAllowInvalidCertificates:YES];
        //validatesDomainName 是否需要验证域名,默认为YES;
        [_manager.securityPolicy setValidatesDomainName:YES];
    }
    
    - (void)setHttpHeader:(NSDictionary *)httpHeader{
        [httpHeader enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [_manager.requestSerializer setValue:obj forHTTPHeaderField:key];
        }];
    }
    - (NSDictionary *)httpHeader{
        return _manager.requestSerializer.HTTPRequestHeaders;
    };
    
    - (void)setMaxOperationCount:(NSInteger)maxOperationCount{
        //请求队列的最大并发数
        _manager.operationQueue.maxConcurrentOperationCount = maxOperationCount;
    }
    #pragma 监测网络的可链接性
    - (BOOL) haveNet {
        if (!_hasReachability) {
            AFNetworkReachabilityManager *reachability = [AFNetworkReachabilityManager sharedManager];
            [reachability setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
                // 当网络状态改变时调用
                switch (status) {
                    case AFNetworkReachabilityStatusUnknown:
                        _netState = YES;
                        if (_netTypeBlock) {
                            _netTypeBlock(tUnknown);
                        }
                        break;
                    case AFNetworkReachabilityStatusNotReachable:
                        _netState = NO;
                        if (_netTypeBlock) {
                            _netTypeBlock(tNotNet);
                        }
                        break;
                    case AFNetworkReachabilityStatusReachableViaWWAN:
                        _netState = YES;
                        if (_netTypeBlock) {
                            _netTypeBlock(tWWAN);
                        }
                        break;
                    case AFNetworkReachabilityStatusReachableViaWiFi:
                        _netState = YES;
                        if (_netTypeBlock) {
                            _netTypeBlock(tWiFi);
                        }
                        break;
                }
            }];
            //开始监控
            [reachability startMonitoring];
            _hasReachability = YES;
        }
        return _netState;
    }
    
    #pragma mark --- 发送请求
    /**
     *  发送get请求
     *   method            请求类型
     *   urlString         请求的网址字符串
     *   parameters        请求的参数
     *   requestResult     请求成功/失败的回调
     */
    - (void)requestWithMethod:(CD_AFMethod)method
                    urlString:(NSString *)urlString
                   parameters:(id)parameters
             withRequestBlock:(RequestResult)requestResult {
        switch (method) {
            case tGet:
                [self getWithURLString:urlString parameters:parameters withRequestBlock:requestResult];
                break;
            case tPost:
                [self postWithURLString:urlString parameters:parameters withRequestBlock:requestResult];
                break;
            case tPut:
                [self putWithURLString:urlString parameters:parameters withRequestBlock:requestResult];
                break;
        }
        
    }
    #pragma mark --- 发送get请求
    /**
     *  发送post请求
     *
     *   URLString         请求的网址字符串
     *   parameters        请求的参数
     *   requestResult     请求成功/失败的回调
     */
    - (void)getWithURLString:(NSString *)urlString
                   parameters:(id)parameters
             withRequestBlock:(RequestResult)requestResult {
        [_manager GET:urlString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            requestResult(responseObject,nil);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            requestResult(nil,error);
        }];
    }
    #pragma mark --- 发送post请求
    /**
     *  发送post请求
     *
     *   URLString         请求的网址字符串
     *   parameters        请求的参数
     *   requestResult     请求成功/失败的回调
     */
    - (void)postWithURLString:(NSString *)urlString
                   parameters:(id)parameters
             withRequestBlock:(RequestResult)requestResult {
        
        [_manager POST:urlString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            requestResult(responseObject,nil);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            requestResult(nil,error);
        }];
    }
    #pragma mark --- 发送put请求
    /**
     *  发送post请求
     *
     *   URLString         请求的网址字符串
     *   parameters        请求的参数
     *   requestResult     请求成功/失败的回调
     */
    - (void)putWithURLString:(NSString *)urlString
                   parameters:(id)parameters
             withRequestBlock:(RequestResult)requestResult {
        
        [_manager PUT:urlString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            requestResult(responseObject,nil);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            requestResult(nil,error);
        }];
    }
    #pragma mark --- 上传图片
    /**
     *  上传图片
     *
     *   URLString         上传图片的网址字符串
     *   parameters        上传图片的参数
     *   uploadParam       上传图片的信息
     *   progress          上传进度的回调
     *   requestResult     上传成功/失败的回调
     */
    - (void)uploadWithURLString:(NSString *)urlString
                     parameters:(id)parameters
                    uploadParam:(NSArray <CD_UploadParam *> *)uploadParams
              withProgressBlock:(ProgressResult)progress
               withRequestBlock:(RequestResult)requestResult {
        [_manager POST:urlString parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
            //上传文件参数
            for (CD_UploadParam *param in uploadParams) {
                switch (param.type) {
                    case tData:
                        [formData appendPartWithFileData:param.fileData name:param.serverName fileName:param.fileName mimeType:param.mimeType];
                        break;
                    case tFileURL:
                        [formData appendPartWithFileURL:[NSURL fileURLWithPath:param.fileURL] name:param.serverName fileName:param.fileName mimeType:param.mimeType error:nil];
                        break;
                    default:
                        break;
                }
            }
        } progress:^(NSProgress * _Nonnull uploadProgress) {
            //打印下上传进度
            //NSLog(@"%lf",1.0 *uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
            progress(uploadProgress);
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            requestResult(responseObject,nil);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            requestResult(nil,error);
        }];
    }
    
    #pragma mark --- 下载数据
    /**
     *  下载数据
     *
     *   URLString         下载数据的网址
     *   parameters        下载数据的参数
     *   progress          下载进度的回调
     *   requestResult     下载成功/失败的回调
     *
     */
    - (void)downLoadWithURLString:(NSString *)urlString
                       parameters:(id)parameters
                withProgressBlock:(ProgressResult)progress
                 withRequestBlock:(RequestResult)requestResult {
    }
    @end
    
    
    2,CD_UploadParam模型类
    /**
     *  文件类型
     */
    typedef NS_ENUM(NSUInteger) {
        tData,
        tFileURL
    }CD_UploadParamType;
    @interface CD_UploadParam : NSObject
    /**
     *  NSData数据
     */
    @property (nonatomic, copy) NSData * fileData;
    /**
     *  文件的FileURL
     */
    @property (nonatomic, copy) NSString * fileURL;
    /**
     *  服务器对应的参数名称
     */
    @property (nonatomic, copy) NSString * serverName;
    /**
     *  文件的名称(上传到服务器后,服务器保存的文件名)
     */
    @property (nonatomic, copy) NSString * fileName;
    /**
     *  文件的MIME类型(image/png,image/jpg,application/octet-stream/video/mp4等)
     */
    @property (nonatomic, copy) NSString * mimeType;
    /**
     *  文件的类型
     */
    @property (nonatomic, assign) CD_UploadParamType type;
    @end
    
    3,示例
    + (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{
                               
                           }
                       }];
        
    };
    
    4,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
    /********************* .m *****************/
    @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
    

    相关文章

      网友评论

      • Maj_sunshine:oc我看懂了 但是swift调用起来是啥呀

      本文标题:干货!Alamofire/AFNetWorking 使用及二次封

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