2016-12-09 10:19:40 dylan_lwb_ 阅读数 1145

//使用方法

let parameters = ["key1" :1, "key2" :2]
WBNetwork.shareInstance.request(requestType: .GET, url:port1, params: parameters, success: {(responseObj)in
    print(responseObj!)
    if responseObj?["code"]as? Int ==0 {

    }
}) {(error) in print(error!) }

//工具类

import UIKit
enum RequestType {
    case GET
    case POST
}
class WBNetwork: AFHTTPSessionManager {

    staticlet shareInstance : WBNetwork = {
        let tool =WBNetwork()
        tool.responseSerializer.acceptableContentTypes?.insert("text/html")
        //tool.responseSerializer.acceptableContentTypes?.insert("text/html" as AnyHashable)
        return tool
    }()

    func request(requestType:RequestType, url : String, params: [String :Any], success: @escaping([String :Any]?) ->(),failure: @escaping( _ error :Error?) -> ()){

        //成功
        let successBlock = { (task:URLSessionDataTask, responseObj:Any?) in
            success(responseObj as? [String :Any])
        }

        //失败
        let failureBlock = {(task :URLSessionDataTask?,error:Error)in
            failure(error)
        }

        //GET
        if requestType == .GET {
            get(url, parameters: params, progress: nil, success: successBlock, failure: failureBlock)
            //get(url, parameters: params, success: successBlock, failure: failureBlock)
        }

        //POST
        if requestType == .POST {
            post(url, parameters: params, progress: nil, success: successBlock, failure: failureBlock)
            //post(url, parameters: params, success: successBlock, failure: failureBlock)
        }
    }
}




2018-07-23 17:40:47 u014651417 阅读数 0
import UIKit

class HCNetWork: AFHTTPSessionManager {
    //单利
    staticletsharedTools:HCNetWork= {
        letbaseUrl =NSURL(string:"http://www.51xianchang.com/")!
        letmanager =HCNetWork.init(baseURL: baseUrlasURL, sessionConfiguration:URLSessionConfiguration.default)
        manager.responseSerializer.acceptableContentTypes = NSSet(objects: "application/json", "text/html", "text/json", "text/javascript", "text/plain") as? Set
        // 设置请求参数为JSON字符串
        manager.requestSerializer = AFJSONRequestSerializer()
        // 请求超时设定
        manager.requestSerializer.timeoutInterval = 10
        // 设置允许自生成证书
        manager.securityPolicy.allowInvalidCertificates = true
        //设置请求头
        manager.requestSerializer.setValue("APP", forHTTPHeaderField:"loginType")
        manager.requestSerializer.setValue("iOS", forHTTPHeaderField:"deviceType")

        returnmanager
    }()
    typealiasrequestBack = (_response:Any?,_error:Error?) -> ()
}
extension HCNetWork {
   
    funcrequestDictionary(urlString:String, parameters: [String:AnyObject]?, finished:@escapingrequestBack) {

        letsuccess = { (task:URLSessionDataTask?, responseObject:Any?) -> ()in
            finished(responseObject,  nil)
        }
        letfailure = { (task:URLSessionDataTask?, error:Error) -> ()in
            finished(nil,  error)
        }
        post(urlString, parameters: parameters, progress:nil, success: success, failure: failure)
    } 
}

自己写的上传 json 参数网络请求, 拿去可用

2018-04-08 12:15:00 weixin_33709364 阅读数 0

先将  afn 用pod导入到 工程中

创建一个类 ZHttpTools 继承自  

AFHTTPSessionManager

一般我们不希望网络请求同时有多个存在,所以我们将这个工具类  设计成单例

代码如下(这个单例是严格仿照 ios的代码写的,你如果说这是个不严谨的单例,要调用allocWithZone  和 copyWithZone才严谨,那么请自行实现,在此不做具体讨论,如果你有空实现了,可以贴到下面的评论里,供大家一起使用。在此只给出标准的写法。)

static let shareInstance: ZHttpTools = {

          let tools = ZHttpTools()

    添加text/html和text/plain",使afn支持json解析

        tools.responseSerializer.acceptableContentTypes?.insert("text/html")

        tools.responseSerializer.acceptableContentTypes?.insert("text/plain")

        return tools

    }()

下面就是对网络请求的封装了

在此只对 get 和 post进行封装

我们用枚举来定义不同的请求类型

enum RequestType:String {

    case GET = "GET"

    case POST = "POST"

}

 

对函数进行封装,代码如下

 

        func request(methodTypea methodType : RequestType, urlString: String, parametersa: Any? , progress downloadProgress: ((Progress) -> Void)?, finished : ((_ result : Any?, _ error : Error?) ->Void)?) {

 

            let successa = { (task : URLSessionDataTask, resulta : Any) in

                finished!(resulta,nil)

            }

            

            let failurea =  { (task : URLSessionDataTask?, errora : Error) in

                finished!(nil, errora)

            }

            

//这里提取出这个progressa 来进一步让大家了解如何抽取闭包(oc 中的 block)

            let progressa = { (progress:Progress) in

                

            }

            

            if methodType == .GET {

                get(urlString, parameters: parametersa, progress: progressa, success: successa, failure: failurea)

            }else {

                post(urlString, parameters: parametersa, progress: progressa, success: successa, failure:failurea)

            }

    }

在控制器调用这个方法

ZHttpTools.shareInstance.request(methodTypea: .GET, urlString: "http://httpbin.org/get", parametersa: [:], progress: { (progress : Progress) in

            

        }) { (result, error) in

            print(result as Any)  //(这里打印出来是 可选类型,请自行解包)

        }

 

封装的文件请来这里

https://github.com/qigemingnan/ZHttptToolFromAFNWithSwiftFour

 

2016-12-19 15:16:08 Mazy_ma 阅读数 2437

一般在一个项目中,网络请求都封装成一个单例,以确保整个项目的网络请求 Session 是同一个.

单例模式定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供.


通过cocoaPods 导入第三方框架

01-切换到项目目录

cd 项目名称

02-初始化Pods

pod init

03-打开 Pods 文件

open Podfile

04-编辑 Podfile

# 设置支持最低平台
platform :ios, '8.0'

target 'TestSwiftMixAFN' do
  # 如果是Swift项目,需添加"use_frameworks!"
  use_frameworks!
pod "AFNetworking"

end

05-安装 Pods

pod install

封装AFN网络请求工具

1 创建一个工具类, 继承自 AFHTTPSessionManager

import AFNetworking

class XMSessionManager: AFHTTPSessionManager {
    // ...
}

2 通过单例创建一个AFHTTPSessionManager 实例

/// 创建网络请求单例
static let shared: XMSessionManager = XMSessionManager()

----------------------------------------------------------------
/// 如果需要设置请求的属性,可在闭包中添加
/// 在第一次访问时,执行闭包,并且将结果保存在 shared 常量中
    static let shared1: XMSessionManager = {

        // 实例化对象
        let manager = XMSessionManager()

        // 设置响应反序列化支持的数据类型
        manager.responseSerializer.acceptableContentTypes?.insert("text/plain")

        // 返回对象
        return manager
    }()

3 通过枚举, 添加HTTP请求方法(GET/POST)

/// 枚举-请求方法
///
/// - GET: GET
/// - POST: POST
enum XMHTTPMethod {
    case GET
    case POST
}

4 自定义网络请求方法,通过闭包回调请求完成后的数据

/// 封装网络请求方法
    ///
    /// - Parameters:
    ///   - Method: GET/POST, 默认是GET请求
    ///   - URLString: 请求地址
    ///   - parameters: 参数
    ///   - completed: 结束回调
    func request(Method:XMHTTPMethod = .GET, URLString: String,parameters: [String: AnyObject]?, completed:@escaping ((_ json: AnyObject?, _ isSuccess: Bool)->())) {

        /// 定义成功回调闭包
        let success = { (task: URLSessionDataTask,json: Any?)->() in
            completed(json as AnyObject?,true)
        }

        /// 定义失败回调闭包
        let failure = {(task: URLSessionDataTask?, error: Error)->() in
            completed(nil,false)
        }

        /// 通过请求方法,执行不同的请求
        // 如果是 GET 请求
        if Method == .GET { // GET

            get(URLString, parameters: parameters, progress: nil, success: success, failure: failure)

        } else { // POST

            post(URLString, parameters: parameters, progress: nil, success: success, failure: failure)
        }
    }

5 网络请求工具的使用

///GET 请求
        XMSessionManager.shared.request(URLString: "http:xxx", parameters: nil, completed:{(json: AnyObject?,isSuccess: Bool)-> () in

            // 请求成功
            if isSuccess {
                print(json ?? "")
            } else {
                print("请求失败")
            }
        })


///POST 请求
     XMSessionManager.shared.request(URLString: "www.xxx.xxx", parameters: ["key":"value" as AnyObject], completed:{(json: AnyObject?,isSuccess: Bool)-> () in
            // 请求成功
            if isSuccess {
                print(json ?? "")
            } else {
                print("请求失败")
            }
        })
2016-08-04 08:56:52 wuxinzhitu 阅读数 1004
一、cocopos的使用
创建项目之后,关闭项目,打开终端,cd 空格 ,把项目所在的文件夹给拖进来, 回车
pod init
然后把项目中生成的那个podfile项目拖到xcode,打开 修改  pod 'AFNetworking'
cmt+S 保存关闭
在终端输入:
pod install --no-repo-update


二、 AFN网络封装

在应用程序开发中,一定要封装隔离网络框架

封装AFN的Get请求.

应用程序在做网络请求的时候不会直接调用到第三方的框架,直接访问在网络工具里面创建的网络请求方法

在网络工具类里面创建网络请求方法

报错:
status code: 200    ………….   unacceptable content-type: text/html
内容格式不支持,把数据进行反序列化格式
这是一个使用AFN时最常见的错误,



OC 封装网络工具

  • 新建网络工具类 NetworkTools
  • 实现单例

+(instancetype)shareTools{
   
static NetTools *tools;
   
   
static dispatch_once_t onceToken;
   
dispatch_once(&onceToken, ^{
       
       
//注意:末尾要包含“/”
       
NSURL *baseURL =[NSURL URLWithString:@"http://www.weather.com.cn/"];
       
        tools =[[
self alloc]initWithBaseURL:baseURL];//BaseURL,指定一个参照的地址,以后只使用参照地址就可以
       
        //设置反序列化格式。
//因为报错:
//        status code: 200    ………….   unacceptable content-type: text/html
//        内容格式不支持
        //直接粘过来:self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
        tools.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json",@"text/javascript",@"text/html",nil];
       
    });
   
   
return tools;

}

  • 建立网络请求方法

//创建网络请求方法
//网络请求时,把请求结果返回给调用方。使用block,异步执行完成把结果返回给调用方
-(void)request:(NSString *)URLString parameters:(id)parameters finished:(void(^)(id result, NSError *error))finished{
    [
self GET:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
       
        finished(responseObject,
nil);
    }
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
       
NSLog(@"%@",error);
        finished(
nil,error);
    }];
}

  • 在调用方里面测试网络请求
[[NetTools shareTools] request:@"data/sk/101010100.html" parameters:nil finished:^(id result, NSError *error) {
       
if (error != nil) {
           
NSLog(@"出错了");
           
return ;
        }
       
NSLog(@"%@",result);
    }];


  • 定义一个HTTP请求类型的枚举类型
//定义一个网络请求类型的枚举
typedef enum :NSUInteger {
    GET,
    POST,
}YSHRequestMethod;

//让他既支持get请求,又支持post请求,所以定义一个结构体类型  扩展这个方法的参数,加一个参数(是判断请求方法的)
-(void)request:(YSHRequestMethod)method URLString:(NSString *)URLString parameters:(id)parameters finished:(void(^)(id result, NSError *error))finished;

 //AFN的网络请求方法,除了单词其他参数都一样的
-------------------------------------------------------------------------
[[NetTools shareTools]request:POST URLString:@"post" parameters:@{@"name": @"zhangsan", @"age": @18} finished:^(id result, NSError *error) {
       
if (error != nil) {
           
NSLog(@"出错了");
           
return ;
        }
       
NSLog(@"%@",result);
    }];


  • 由于get和post的网络请求方法,基本一致,所以封装代码


//AFN的网络请求方法,除了单词其他参数都一样的
   
   
//判断传过来的请求方式
   
NSString *methodName = (method == GET) ? @"GET" : @"POST";
   
   
//点进去看发现GETPOST等都有一个相同的方法,所以使用,但是智能提示不出来,所以。。。
    //dataTaskWithHTTPMethod本类没有实现方法,但是父类实现了
    // 在调用方法的时候,如果本类没有提供,直接调用父类的方法,AFN 内部已经实现这个方法!
//需要补全方法中的参数。
    [[self dataTaskWithHTTPMethod:methodName URLString:URLString parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
        finished(responseObject,
nil);
    }
failure:^(NSURLSessionDataTask *task, NSError *error) {
       
NSLog(@"%@",error);
        finished(
nil,error);
    }] resume];


  • 从 AFHTTPSessionManager.m 中复制 dataTaskWithHTTPMethod 函数定义

因为那个方法是私有的方法,不能直接调用这个内部方法

在使用的地方,定义一个协议,把方法给粘过来

OC没有任何的严谨性

我们通过协议把他的一个内部的私有的方法的定义给拿出来,然后操作这个原本私有的方法。可以直接使用这个私有的方法了。

调用私有的API,但不能调用苹果的私有API,否则不能上架。

/// 网络工具协议
@protocol NetworkToolsProxy <NSObject>

/// 网络请求方法
///
/// @param method     HTTP 请求方法
/// @param URLString  URLString
/// @param parameters 参数字典
/// @param success    成功回调
/// @param failure    失败回调
///
/// @return NSURLSessionDataTask

@optional//可以不实现,因为我们是利用继承的特点,调用了父类的方法
- (
NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                       URLString:(
NSString *)URLString
                                      parameters:(
id)parameters
                                         success:(
void (^)(NSURLSessionDataTask *, id))success
                                         failure:(
void (^)(NSURLSessionDataTask *, NSError *))failure;

@end

///协议是让人遵守的,遵守协议
/// 遵守网络协议 - 为了能够欺骗 Xcode 给一个智能提示,以及编译通过!
@interface NetTools ()<NetworkToolsProxy>

@end


Swift 封装网络工具

  • 新建网络工具类 NetworkTools
  • 实现单例
// MARK: 网络工具
class NetworkTools: AFHTTPSessionManager {

   
//1.设置网络工具单例 & 响应格式设置方法
    static let sharedTools:NetworkTools = {
       
let tools = NetworkTools(baseURL: nil)
       
       
// 设置反序列化数据格式 - 系统会自动将 OC 框架中的 NSSet 转换成 Set
        tools.responseSerializer.acceptableContentTypes?.insert("text/html")
       
return tools
    }()
}

  • 定义网络请求方法枚举
//定义HTTP请求方法枚举
enum YSHRequestMethod: String {
   
case GET = "GET"
   
case POSE = "POSE"
}


  • 创建网络请求方法
// MARK: - 封装 AFN 网络方法
extension NetworkTools {
   
   
/// 网络请求
    ///
    /// - parameter method:     GET / POST
    /// - parameter URLString:  URLString
    /// - parameter parameters: 参数字典
    /// - parameter finished:   完成回调
    func requedt(method:YSHRequestMethod,URLString: String,parameters:[String:AnyObject]?,finsished: (result:AnyObject?,error:NSError?) ->() ){
       
       
       
if method == YSHRequestMethod.GET {
           
//不需要用下划线替掉
            GET(URLString, parameters: parameters, success: { (_, result) -> Void in
                finsished(result: result, error:
nil )
                }, failure: { (
_, error) -> Void in
                   
print(error)
                    finsished(result:
nil, error: error)
            })
        }
       
else{
           
POST(URLString, parameters: parameters, success: { (_, result) -> Void in
               
               
// 在开发网络应用的时候,错误不要提示给用户,但是错误一定要输出!
                finsished(result: result, error: nil)
               
                }, failure: { (
_, error) -> Void in
                   
                    finsished(result:
nil, error: error)
            })
        }
    }
}

  • AFN 内部网络方法封装
//闭包是可以提前准备好的代码,在需要的时候调用执行,可以当做参数传递
       
       
// 定义成功回调的闭包
        //想要把success传递到下面,则这个闭包的参数格式,必须和下面调用的地方的闭包的参数格式是一致的,可以直接粘贴GET调用的地方的闭包的代码。
       
       
let success = {
            (task:
NSURLSessionDataTask,result: AnyObject?) -> Void in
            finsished(result: result, error:
nil )
        }
       
       
// 定义失败回调的闭包
        let failure = { (task:NSURLSessionDataTask?,error: NSError) -> Void in
           
// 在开发网络应用的时候,错误不要提示给用户,但是错误一定要输出!
            print(error)
            finsished(result:
nil, error: error)
        }

       
       
//优化封装
        if method == YSHRequestMethod.GET {
           
GET(URLString, parameters: parameters, success: success, failure: failure)
        }
       
else{
           
POST(URLString, parameters: parameters, success: success, failure: failure)
        }


  • 测试 POST 请求

NetworkTools.sharedTools.requedt(YSHRequestMethod.POSE, URLString: "http://httpbin.org/post", parameters: ["name": "wanglaowu"]) { (result, error) -> () in
           
print(result)
        }


小结

  • 使用 typealias 可以统一和简化闭包的定义和传递
  • 使用 baseURL 能够简化网络访问方法中 URL 的传递
  • AFN 访问方法最常见的错误
    • status code == 200,但是提示 unacceptable content-type,表示网络访问正常,但是无法对返回数据做反序列化
    • 解决办法:增加 反序列化数据 格式
  • 另外一个常见错误
    • status code == 405,不支持的网络请求方法,检查 GET / POST 是否写错