• iOS


    前言

    • Alamofire 是 Swift 语言的 HTTP 网络开发工具包,相当于 Swift 实现 AFNetworking 版本。当然,AFNetworking 非常稳定,在 Mac OSX 与 iOS 中也能像其他 Objective-C 代码一样用 Swift 编写。不过 Alamofire 更适合 Swift 语言风格习惯(Alamofire 与 AFNetworking 可以共存一个项目中,互不影响)。Alamofire 取名来源于 Alamo Fire flower。

    • Alamofire 的核心主要是试图简化 iOS 中 HTTP 网络连接,它通过使用 NSURLSession 以及 Foundation URL Loading System 来创建一个 Swift 本地的网络访问接口,从而实现令人难以置信效率的任务。

    1、Alamofire

    • Alamofire 功能:

      • Chainable Request / Response methods
      • URL / JSON / plist Parameter Encoding
      • Upload File / Data / Stream
      • Download using Request or Resume data
      • Authentication with NSURLCredential
      • Progress Closure & NSProgress
      • cURL Debug Output
    • Alamofire 系统需求:

      Alamofire Version     |    Minimum iOS Target    |          Target Notes
      

      ------------------------|--------------------------|-------------------------------------------------------------------
      3.4.x | iOS 8.0+ | Xcode 7.3+ is required.
      3.1.4 -> 3.3.1 | iOS 8.0+ | Xcode 7.2+ is required.
      3.1.0 -> 3.1.3 | iOS 8.0+ | Xcode 7.1+ is required.
      2.0.0 -> 3.0.1 | iOS 8.0+ | Xcode 7.0+ is required.
      1.3.0 -> 1.3.1 | iOS 7.0+ | Xcode 6.4 is required.
      1.2.1 -> 1.2.3 | iOS 7.0+ | Xcode 6.3 is required.
      1.1.0 -> 1.2.0 | iOS 7.0+ | Xcode 6.1 is required.
      1.0.0 -> 1.0.1 | iOS 7.0+ | Xcode 6.0 is required. For Xcode 6.1, use the xcode-6.1 branch.

    • Alamofire 有许多让程序猿信服去使用它的理由。在 iOS 开发中,使用 NURLSession 是 HTTP 网络的未来趋势, 相比 NSURLConnection 来说,它的功能更加丰富:

      • 后台上传和下载
      • 暂停以及重新开始网络操作的能力
      • 可配置的容器(Container)
      • 子类和私有存储
      • 改进的认证处理
      • 对每个基础连接进行身份验证
      • 多种代理模式 -- NSURLConnection 拥有异步代码块的基本方法, 但是不能用它们的代理,NSURLSession 具有一种混合型的方法。
    • 对 AFNetworking 能做而 Alamofire 不能做的有以下几点:

      • UIKit 扩展
      • TLS 验证
      • NSOperation/NSURLConnection/AFURLConnectionOperation 调用
      • 多重 HTTP 网络请求构架

    2、Alamofire 的添加

    • Github 网址:https://github.com/Alamofire/Alamofire

    • Alamofire 使用 ARC

    • Swift

      	// 将第三方库文件复制到工程目录下
      	Alamofire		
      	
      	// 将第三方库文件中的 xcodeproj 添加到工程中
      	Alamofire.xcodeproj
          
      	// 在 TARGETS -> General -> Embedded Binaries 下添加静态库文件(添加上边的)
      	Alamofire.framework
          
      	// 添加头文件
      	import Alamofire
      

    3、Alamofire 的设置

    • Swift

      • 请求超时时间设置

        	// 必须设置为全局的
        	var alamofireManager: Manager!
        	
        	let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        	config.timeoutIntervalForRequest = 5     // 秒
          	
        	self.alamofireManager = Manager(configuration: config)
        	self.alamofireManager.request(.GET, "http://120.25.226.186:32812/video?type=JSON")
        
      • HTTP 方法(Medthods)

        	Alamofire.Method enum 列表出在 RFC 2616 中定义的 HTTP 方法:
        
        		public enum Method: String {
        
        			case OPTIONS = "OPTIONS"
        			case GET = "GET"
        			case HEAD = "HEAD"
        			case POST = "POST"
        			case PUT = "PUT"
        			case PATCH = "PATCH"
        			case DELETE = "DELETE"
        			case TRACE = "TRACE"
        			case CONNECT = "CONNECT"
        		}
        
        	这些值可以作为 Alamofire.request 请求的第一个参数。
                
        	Alamofire.request(.POST, "https://httpbin.org/post")
            
        	Alamofire.request(.PUT, "https://httpbin.org/put")
            
        	Alamofire.request(.DELETE, "https://httpbin.org/delete")
        
      • 请求参数编码方式设置

            Alamofire 使用 Alamofire.ParameterEncoding 可以支持 URL query/URI form,JSON,PropertyList 方式编码参数。
        
            enum ParameterEncoding {
                
                case URL
                case URLEncodedInURL
                case JSON
                case PropertyList(NSPropertyListFormat, NSPropertyListWriteOptions)
                case Custom((URLRequestConvertible, [String : AnyObject]?) -> (NSMutableURLRequest, NSError?))
                
                public func encode(URLRequest: URLRequestConvertible, parameters: [String : AnyObject]?) -> (NSMutableURLRequest, NSError?)
                public func queryComponents(key: String, _ value: AnyObject) -> [(String, String)]
                public func escape(string: String) -> String
            }
         	
            // URL 形式参数编码
            
             	// 发送以下 HttpBody 内容: foo=bar&baz[]=a&baz[]=1&qux[x]=1&qux[y]=2&qux[z]=3
            
            	let urlStr:URLStringConvertible = "https://httpbin.org/post"
            	let parameters:[String: AnyObject]? = ["foo":"bar", "baz":["a", 1], "qux":["x":1, "y":2, "z":3]]
            
                Alamofire.request(.POST, urlStr, parameters: parameters)        // 默认编码方式是 URL
            
        		Alamofire.request(.POST, urlStr, parameters: parameters, encoding: .URL)
        
            // JSON 形式参数编码
            
             	// 发送以下 HttpBody 内容: {"foo":"bar", "baz":["a", 1], "qux":{"x":1, "y":2, "z":3}}
            
            	let urlStr:URLStringConvertible = "https://httpbin.org/post"
            	let parameters:[String: AnyObject]? = ["foo":"bar", "baz":["a", 1], "qux":["x":1, "y":2, "z":3]]
            
                Alamofire.request(.POST, urlStr, parameters: parameters, encoding:.JSON)                		
        
            // URLRequest 请求编码
        
                let url = NSURL(string: "https://httpbin.org/get")!
                var urlRequest = NSMutableURLRequest(URL: url)
                    
                let param = ["foo": "bar"]
                let encoding = Alamofire.ParameterEncoding.URL
            
                (urlRequest, _) = encoding.encode(urlRequest, parameters: param)
        
      • 请求头设置

        	let headers = ["User-Agent":"iPhone 6s Plus"]
            
        	Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON", headers: headers)
          	
         	// 不设置时为默认值
        	Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
        
      • 请求数据响应格式设置

        	Built-in Response Methods:
        
        		response()
        		responseData()
        		responseString(encoding:NSStringEncoding)
        		responseJSON(options:NSJSONReadingOptions)
        		responsePropertyList(options:NSPropertyListReadOptions)
        
        	可以同时响应多种格式数据。
        
        	// 响应 NSData 格式数据
            	
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
        
        			.response { (request:NSURLRequest?, response:NSHTTPURLResponse?, responseData:NSData?, error:NSError?) in
                
        				/*
        					网络请求结束,成功时 error == nil。请求返回的数据存在 responseData 中,为 NSData 格式。
        				*/	
        			}
            
        	// 响应 String 格式数据
            		
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
        
        			.responseString { (response:Response<String, NSError>) in
                    
        				/*
        						网络请求结束,成功时 response.result.error == nil。请求返回的数据存在 response.result.value 中,为 String 格式。
                      		或者成功时 response.result 的值为 .Success,失败时 response.result 的值为 .Failure。
        				*/	
        
        				response.request     // original URL request
        				response.response    // URL response
        				response.data        // server data
        				response.result      // result of response serialization
        
        				// 获取并判断结果值
        
        				if let string = response.result.value {
                            	
        				} else {
                            	
        				}
                        
        				// 判断结果值
        
        				if response.result.error == nil {
        
        				} else {
        
        				}
                        
        				// 判断结果值
        
        				switch response.result {
                            
        					case.Success(let value):
        					case.Failure(let error):
        				}
        			}
            
        	// 响应 JSON 格式数据
            	
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
        
        			.responseJSON { (response:Response<AnyObject, NSError>) in
                    
        				/*
        					网络请求结束,成功时 response.result.error == nil。请求返回的数据存在 response.result.value 中,为 JSON 格式。
        					或者成功时 response.result 的值为 .Success,失败时 response.result 的值为 .Failure。
        				*/	
        			}
            
        	// 响应 PList 格式数据
            	
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
        
        			.responsePropertyList { (response:Response<AnyObject, NSError>) in
        
        				/*
                    		网络请求结束,成功时 response.result.error == nil。请求返回的数据存在 response.result.value 中,为 PList 格式。
        					或者成功时 response.result 的值为 .Success,失败时 response.result 的值为 .Failure。
        				*/	
        			}
        
        	// 响应 多种格式 数据
        
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
        
                 	// 参数不使用时可以省略
        			.response { (_, _, responseData:NSData?, error:NSError?) in
        
        			}
        
        			.responseJSON { (response:Response<AnyObject, NSError>) in
        
        			}
        
      • Request 请求创建方式

        	// Manager 方式
            
            	// 必须设置为全局的
        		var alamofireManager: Manager!
        
        		self.alamofireManager = Manager(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
            
        		self.alamofireManager.request(.GET, "http://120.25.226.186:32812/video?type=JSON")
            
        	// Alamofire 方式,接收返回值
            
        		let request = Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
            
        	// 不接收返回值,request 不带参数
        
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
        
        	// request 带参数
        
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video", parameters: ["type": "JSON"])
        	
        	// request 带参数及参数编码方式
        
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video", parameters: ["type": "JSON"], encoding: .URL)
                	
        	// request 带参数及请求头
                
        		Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video", parameters: ["type": "JSON"], 
        		                                                                       encoding: .URL, 
        		                                                                        headers: ["User-Agent":"iPhone 6s"])
        
      • 请求任务创建方式

        	// 数据请求 request (GET/POST)
            
        		// Alamofire GET 方式
                
        			let urlStr:URLStringConvertible = "http://192.168.88.200:8080/MJServer/video?type=XML"
                    
        			Alamofire.request(.GET, urlStr)
            
        		// Alamofire POST 方式
                
        			let urlStr:URLStringConvertible = "http://192.168.88.200:8080/MJServer/video"
                
        			Alamofire.request(.GET, urlStr, parameters: ["type": "XML"])
                
        		// Manager GET 方式
                
                	// 必须设置为全局的
        			var alamofireManager: Manager!
        
        			let urlStr:URLStringConvertible = "http://192.168.88.200:8080/MJServer/video?type=XML"
                    
        			self.alamofireManager = Manager(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
                    
        			self.alamofireManager.request(.GET, urlStr)
            
        		// Manager POST 方式
                
                	// 必须设置为全局的
        			var alamofireManager: Manager!
        
        			let urlStr:URLStringConvertible = "http://192.168.88.200:8080/MJServer/video"
                
        			self.alamofireManager = Manager(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
                
        			self.alamofireManager.request(.GET, urlStr, parameters: ["type": "XML"])
            
        	// 文件下载 download
            	
        		// 指定文件路径方式
            	
                	Alamofire.download(.GET, "http://120.25.226.186:32812/resources/videos/minion_01.mp4") 
                	          { (temporaryURL:NSURL, response:NSHTTPURLResponse) -> NSURL in
                        
                		/*
                				设置文件下载路径,temporaryURL 是沙盒下的文件临时存储路径,下载完成后会被自动删除。response.suggestedFilename 
                			为服务器端文件名。此 block 在子线程中执行。
                		*/
                        
                		return documentsDirUrl
                	}
                        
                		.progress { (bytesWrite:Int64, totalBytesWrite:Int64, totalBytesExpectedToWrite:Int64) in
                            
                			/*
                				监听文件下载进度,此 block 在子线程中执行。
                			*/
                		}
                        
                		.response { (_, _, _, error:NSError?) in
                            
                			/*
                				网络请求结束,成功时 error == nil。在 Swift 中文件已经存在时,再次相同路径写入会失败。
                			*/
                		}
            
        		// 使用默认提供的下载路径方式
            
                	Alamofire.download(.GET, "http://120.25.226.186:32812/resources/videos/minion_01.mp4", destination: destination)
                        
                		.progress { (bytesWrite:Int64, totalBytesWrite:Int64, totalBytesExpectedToWrite:Int64) in
                            
                			/*
                				监听文件下载进度,此 block 在子线程中执行。
                			*/
                		}
                        
                		.response { (_, _, _, error:NSError?) in
                            
                			/*
                				网络请求结束,成功时 error == nil。在 Swift 中文件已经存在时,再次相同路径写入会失败。
                			*/
                		}
            
        		// 断点续传下载方式
            	
        			let downloadRequest:Request = Alamofire.download(resumeData: resumeData, 
                	                                                destination: { (temporaryURL:NSURL, 
                	                                                                    response:NSHTTPURLResponse) -> NSURL in
                        
        				/*
        						设置文件下载路径,temporaryURL 是沙盒下的文件临时存储路径,下载完成后会被自动删除。response.suggestedFilename 
        					为服务器端文件名。此 block 在子线程中执行。
        				*/
                            
        				return documentsDirUrl
        			})
                        
        				.progress { (bytesWrite:Int64, totalBytesWrite:Int64, totalBytesExpectedToWrite:Int64) in
                            
        					/*
        						监听文件下载进度,此 block 在子线程中执行。
        					*/
        				}
                        
        				.response { (_, _, data:NSData?, error:NSError?) in
                            
        					/*
        						网络请求结束,成功时 error == nil。在 Swift 中文件已经存在时,再次相同路径写入会失败。
        					*/
        				}
            	
        	// 文件上传 upload
            
        		// Data 形式上传
            	
        			Alamofire.upload(.POST, "http://192.168.88.200:8080/MJServer/upload", headers: headers, data: formBody)
                        
        				.progress { (bytesLoad:Int64, totalBytesLoad:Int64, totalBytesExpectedToLoad:Int64) in
                            
        					/*
        						监听文件上传进度,此 block 在子线程中执行。
        					*/
        				}
                        
        				.response { (_, _, responseData:NSData?, error:NSError?) in
                            
        					/*
        						网络请求结束。
        					*/
        				}
            
        		// MultipartFormData 形式上传
            
        			Alamofire.upload(.POST, "http://192.168.88.200:8080/MJServer/upload", 
        			                         multipartFormData: { (formData:MultipartFormData) in
                        
        				/*
        					添加参数。第一个参数是需要添加的参数内容值,第二个是后台规定的参数名。
        					设置上传的文件。第一个参数是需要上传的文件路径,第二个是后台规定的参数名,第三个是上传后服务器端文件名称,第四个是文件类型。
        				*/
                        
        			}) { (encodingResult:Manager.MultipartFormDataEncodingResult) in
                        
        				/*
        					数据编码完成。
        				*/
                        
        				switch encodingResult {
                      
                      	// 编码成功
                       	case .Success(let uploadRequest, _, _):                                                                 
                            
                           	uploadRequest
                                
                             	.progress { (bytesLoad:Int64, totalBytesLoad:Int64, totalBytesExpectedToLoad:Int64) in
                                
                                	/*
                                		监听文件上传进度,此 block 在子线程中执行。
                                	*/
                             	}
                                
                             	.response { (_, _, responseData:NSData?, error:NSError?) in
                                    
                                	/*
                                		网络请求结束。
                                	*/
                             	}
                                
                       	// 编码失败
                       	case .Failure(let error):                                                                               
                            
                       		print(error)
        				}
        			}
        
      • 请求任务设置

        	// 继续请求任务
        	downloadRequest.resume()
            
        	// 暂停请求任务
         	downloadRequest.suspend()
            
        	// 取消请求任务
         	downloadRequest.cancel()
        
      • 文件下载设置

        	// 设置文件下载路径
        
            	let documentsDirUrl:NSURL = NSFileManager.defaultManager()
            	                                         .URLsForDirectory( .DocumentDirectory, inDomains: .UserDomainMask)[0]
            	                                         .URLByAppendingPathComponent(response.suggestedFilename!)
        
            	if NSFileManager.defaultManager().fileExistsAtPath(documentsDirUrl.path!) {
                
                	// 移除已经存在的文件,在 Swift 中文件已经存在时,再次相同路径写入会失败
                	try! NSFileManager.defaultManager().removeItemAtURL(documentsDirUrl)
            	}
        
        	// 设置文件默认下载路径
        
            	let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
        
        	// 监听文件下载进度
        
        		bytesWrite                  // 本次写入的大小
        		totalBytesWrite             // 已经写入的大小
          		totalBytesExpectedToWrite   // 总大小
            
            	// 设置下载进度条
            	let progressNum:NSNumber = NSNumber(float: Float(Double(totalBytesWrite)/Double(totalBytesExpectedToWrite)))
            	self.performSelectorOnMainThread(#selector(ViewController.refreshProgress(_:)), withObject: progressNum, waitUntilDone: true)
        
      • 文件上传设置

        	// Data 形式上传
        
            	let boundary = "myBoundary"
            
            	// 设置请求头
        		/*
            		upload task 不会在请求头里添加 content-type (上传数据类型)字段,@"myBoundary" 为请求体边界,参数可以随便设置,但需一致
            	*/
            	let headers = ["Content-Type":"multipart/form-data; charset=utf-8; boundary=(boundary)"]
        
            	// 设置请求文件参数
            
                	let formBody = NSMutableData()
                
                	// 参数开始分割线
                	/*
                		每个参数开始前都需要加
            		*/
                	formBody.appendData("--(boundary)".dataUsingEncoding(NSUTF8StringEncoding)!)
                	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
                
                	// 参数
                	formBody.appendData("Content-Disposition: form-data; name="("username")"
        
        ("jhq")"
                	        .dataUsingEncoding(NSUTF8StringEncoding)!)
                
                	// username 是后台规定的参数名,jhq 是需要添加的参数内容值
                	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
                
                	// 文件开始分割线
                	/*
                		每个文件开始前都需要加
                	*/
                	formBody.appendData("--(boundary)".dataUsingEncoding(NSUTF8StringEncoding)!)
                	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
                
                	// 文件参数名
                	formBody.appendData("Content-Disposition: form-data; name="("file")"; filename="("test.mp4")""
                	        .dataUsingEncoding(NSUTF8StringEncoding)!)
                	        
                	// file 是后台规定的参数名,test.mp4 为上传后服务器端文件名称
                	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)                    		
                
                	// 文件的类型
                	formBody.appendData("Content-Type: mp4".dataUsingEncoding(NSUTF8StringEncoding)!)
                	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
                	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
                
                	// 待上传文件数据
                	/*
                		本地待上传的文件路径
                	*/
                	formBody.appendData(NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("minion", ofType: "mp4")!)!)
                	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
                
                	// 结束分割线标记
                	formBody.appendData("--(boundary)--".dataUsingEncoding(NSUTF8StringEncoding)!)
                	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
        	
        	// 指定文件路径形式上传
        	/*
        		public func appendBodyPart(fileURL fileURL: NSURL, name: String, fileName: String, mimeType: String);
         
        		第一个参数是需要上传的文件路径,第二个是后台规定的参数名,第三个是上传后服务器端文件名称,第四个是文件类型。
        	*/
        	let fileUrl = NSBundle.mainBundle().URLForResource("HQ_0005", withExtension: "jpg")!
        	formData.appendBodyPart(fileURL: fileUrl, name: "file", fileName: "test.png", mimeType: "image/jpeg")
            
        	// 指定文件数据形式上传
        	/*
        		public func appendBodyPart(data data: NSData, name: String, fileName: String, mimeType: String);
                 
        		第一个参数是需要上传的文件数据,第二个是后台规定的参数名,第三个是上传后服务器端文件名称,第四个是文件类型。
        	*/
        	let fileData = NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("minion", ofType: "mp4")!)
        	formData.appendBodyPart(data: fileData!, name: "file", fileName: "test.mp4", mimeType: "mp4")
        
        	// 添加参数
        	/*
        		public func appendBodyPart(data data: NSData, name: String);
                 
        		第一个参数是需要添加的参数内容值,第二个是后台规定的参数名。
        	*/
        	formData.appendBodyPart(data: "jhq".dataUsingEncoding(NSUTF8StringEncoding)!, name: "username")
                
        	// 监听文件上传进度
        
        	bytesLoad                   // 本次写入的大小
        	totalBytesLoad              // 已经写入的大小
        	totalBytesExpectedToLoad    // 总大小
            
        	let progressNum1:NSNumber = NSNumber(float: Float(Double(totalBytesLoad)/Double(totalBytesExpectedToLoad)))
        	self.performSelectorOnMainThread(#selector(ViewController.refreshProgress(_:)), withObject: progressNum1, waitUntilDone: true)
        

    4、Alamofire HTTP 认证

    • 支持以下几种认证:

      • HTTP Basic
      • HTTP Digest
      • Kerberos
      • NTLM
    • Swift

      	// Http basic 方式认证
      	
          	let user = "user"
          	let password = "password"
          
          	Alamofire.request(.GET, "https://httpbin.org/basic-auth/(user)/(password)")
      
              	.authenticate(user: user, password: password)
      
      	// NSURLCredential 方式认证
      	
          	let user = "user"
          	let password = "password"
          
          	let credential = NSURLCredential(user: user, password: password, persistence: .ForSession)
          
          	Alamofire.request(.GET, "https://httpbin.org/basic-auth/(user)/(password)")
      
              	.authenticate(usingCredential: credential)
      
      	// headers 方式认证
      	
          	let user = "user"
          	let password = "password"
          
          	let credentialData = "(user):(password)".dataUsingEncoding(NSUTF8StringEncoding)!
          	let base64Credentials = credentialData.base64EncodedStringWithOptions([])
          
          	let headers = ["Authorization": "Basic (base64Credentials)"]
          
          	Alamofire.request(.GET, "https://httpbin.org/basic-auth/user/password", headers: headers)
      

    5、Alamofire HTTP 响应状态信息识别

    • Swift

      • 手动识别

        	/*
        			Alamofire 还提供了 HTTP 响应状态的判断识别,通过 validate 方法,对于在我们期望之外的 HTTP 响应状态信息,
        		Alamofire 会提供报错信息:
        	*/
        	
        	Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
                
        		.validate(statusCode: 200..<300)
                
        		.validate(contentType: ["application/json"])
        
      • 自动识别

        	// validate 方法还提供自动识别机制,我们调用 validate 方法时不传入任何参数,则会自动认为 200…299 的状态吗为正常:
        
        	Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
                
        		.validate()
        

    6、Alamofire Timeline

    • Swift

      	/*
      			Alamofire collects timings throughout the lifecycle of a Request and creates a Timeline object 
      		exposed as a property on a Response.
         	*/
         	
      	Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video", parameters: ["type": "JSON"])
      
        		.validate()
      
        		.responseJSON { response in
      
             	print(response.timeline)
      	}
      
      	The above reports the following Timeline info:
          
          	Latency: 0.428 seconds
          	Request Duration: 0.428 seconds
          	Serialization Duration: 0.001 seconds
          	Total Duration: 0.429 seconds
      

    7、Alamofire 调试打印

    • Swift

      	// GET print
      	
          	let request = Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
          
          	print(request)
      
      		// 打印输出 GET http://192.168.88.200:8080/MJServer/video?type=JSON
        	
      	// POST print
      	
          	let request = Alamofire.request(.POST, "http://192.168.88.200:8080/MJServer/video", parameters: ["type":"JSON"])
          
          	print(request)
      
      		// 打印输出 POST http://192.168.88.200:8080/MJServer/video
         	
      	// GET debugprint
      	 
          	let request = Alamofire.request(.GET, "http://192.168.88.200:8080/MJServer/video?type=JSON")
          
          	debugPrint(request)
      
      		// 打印输出 curl 信息
      
          	$ curl -i 
               	-H "User-Agent: SwiftAlamofire/com.qianqianstudio.SwiftAlamofire (1; OS Version 9.3 (Build 13E230))" 
               	-H "Accept-Language: zh-Hans-US;q=1.0, en-US;q=0.9" 
               	-H "Accept-Encoding: gzip;q=1.0, compress;q=0.5" 
               		"http://192.168.88.200:8080/MJServer/video?type=JSON"
      

    8、Alamofire 网络连接状态检查

    • Swift

      	网络连接状态:
       
           	public enum NetworkReachabilityStatus {
               	case Unknown            网络状态未知
               	case NotReachable       无网络连接
               	case Reachable(Alamofire.NetworkReachabilityManager.ConnectionType)
           	}
          
           	public enum ConnectionType {
               	case EthernetOrWiFi     WiFi 网络
               	case WWAN               无线网络(蜂窝移动网络)
           	}
         	
      	let manager = NetworkReachabilityManager()
          
        	// 监听网络状态闭包
      	manager?.listener = { status in
              
      		/*
          		开启网络状态监听后,只要网络状态发生改变就会调用该闭包代码段。
      	 	*/
            
      		print("Network Status Changed: (status)")
      	}
         
         	// 开启监听网络状态
      	manager?.startListening()
        
        	// 关闭网络状态监听
      	manager?.stopListening()
         
         	// 获取网络连接状态
      	let status = manager?.networkReachabilityStatus
        	
        	// 判断网络是否连接
      	let isReachable:Bool? = manager?.isReachable
        	
        	// 判断 WiFi 是否连接
      	let isReachableOnEthernetOrWiFi:Bool? = manager?.isReachableOnEthernetOrWiFi
        	
        	// 判断 无线网络 是否连接
      	let isReachableOnWWAN:Bool? = manager?.isReachableOnWWAN
      

    9、Alamofire 异步 GET 数据请求

    • Swift

      	// Alamofire 方式
          
          	let urlStr:URLStringConvertible = "http://192.168.88.200:8080/MJServer/video?type=XML"
      
          	Alamofire.request(.GET, urlStr)
          
              	.response { (request:NSURLRequest?, response:NSHTTPURLResponse?, responseData:NSData?, error:NSError?) in
      
                  	/*
      					网络请求结束,成功时 error == nil。请求返回的数据存在 responseData 中,为 NSData 格式。
                  	*/
              	}
      	
      	// Manager 方式
          
          	// 必须设置为全局的
      		var alamofireManager: Manager!
          
          	let urlStr:URLStringConvertible = "http://192.168.88.200:8080/MJServer/video?type=XML"
      
          	self.alamofireManager = Manager(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
          
          	self.alamofireManager.request(.GET, urlStr)
              
              	.response { (request:NSURLRequest?, response:NSHTTPURLResponse?, responseData:NSData?, error:NSError?) in
                  
                  	/*
                   		网络请求结束,成功时 error == nil。请求返回的数据存在 responseData 中,为 NSData 格式。
                   	*/
              	}
      

    10、Alamofire 文件下载

    • 支持的类型:

      • Request
      • Resume Data
    • 默认支持后台方式下载

    • Swift

      • 指定文件路径方式

        	// 目标路径闭包展开
        
        	Alamofire.download(.GET, "http://120.25.226.186:32812/resources/videos/minion_01.mp4") 
        	                  { (temporaryURL:NSURL, response:NSHTTPURLResponse) -> NSURL in
        
        		/*
        				设置文件下载路径,temporaryURL 是沙盒下的文件临时存储路径,下载完成后会被自动删除。response.suggestedFilename 
        			为服务器端文件名。此 block 在子线程中执行。
        		*/
            
        		let documentsDirUrl:NSURL = NSFileManager.defaultManager()
        		                                         .URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
        		                                         .URLByAppendingPathComponent(response.suggestedFilename!)
            
        		if NSFileManager.defaultManager().fileExistsAtPath(documentsDirUrl.path!) {
                
                	// 移除已经存在的文件,在 Swift 中文件已经存在时,再次相同路径写入会失败
                	try! NSFileManager.defaultManager().removeItemAtURL(documentsDirUrl)                
        		}	
        
        		return documentsDirUrl
        	}
        
        		.progress { (bytesWrite:Int64, totalBytesWrite:Int64, totalBytesExpectedToWrite:Int64) in
                
        			/*
        				监听文件下载进度,此 block 在子线程中执行。
        			*/
                	
                	// 设置下载进度条 
        			let progressNum:NSNumber = NSNumber(float: Float(Double(totalBytesWrite)/Double(totalBytesExpectedToWrite)))
        			self.performSelectorOnMainThread(#selector(ViewController.refreshProgress(_:)), withObject: progressNum, waitUntilDone: true)
        		}
            
        		.response { (_, _, _, error:NSError?) in
        
        			/*
        				网络请求结束,成功时 error == nil。在 Swift 中文件已经存在时,再次相同路径写入会失败。
        			*/	
        		}
        
      • 使用默认提供的下载路径方式

        	// 目标路径闭包
            	
            	// 设置文件的默认下载路径
            	let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
            	
            	Alamofire.download(.GET, "http://120.25.226.186:32812/resources/videos/minion_01.mp4", destination: destination)
                	
                	.progress { (bytesWrite:Int64, totalBytesWrite:Int64, totalBytesExpectedToWrite:Int64) in
                 	
                    	/*
        					监听文件下载进度,此 block 在子线程中执行。
                    	*/
                    
                    	// 设置下载进度条
                    	let progressNum:NSNumber = NSNumber(float: Float(Double(totalBytesWrite)/Double(totalBytesExpectedToWrite)))
                    	self.performSelectorOnMainThread(#selector(ViewController.refreshProgress(_:)), 
                    	                      withObject: progressNum, 
                    	                   waitUntilDone: true)
                	}
                	
                	.response { (_, _, _, error:NSError?) in
        			
                    	/*
                        	网络请求结束,成功时 error == nil。在 Swift 中文件已经存在时,再次相同路径写入会失败。
                    	*/
        			}
        
      • 断点续传下载方式

        	// 使用断点下载需要之前下载的临时文件存在,才能继续下载。
        
        	var downloadRequest:Request!
        	var resumeData:NSData!
        
        	// 开始下载
        	
            	let resumeTmpPath = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true)[0] + "/resumeData.tmp"
            
            	// 判断断点保存的文件是否存在
            	if NSFileManager.defaultManager().fileExistsAtPath(resumeTmpPath) {
        
            		// 断点开始下载
            	
                	// 读取断点保存的数据
                	self.resumeData = NSData(contentsOfFile: resumeTmpPath)
        
                	self.downloadRequest = Alamofire.download(resumeData: self.resumeData, destination: 
                	                                 { (temporaryURL:NSURL, response:NSHTTPURLResponse) -> NSURL in
                    	
                   	let documentsDirUrl:NSURL = NSFileManager.defaultManager()
                   	                                         .URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
                   	                                         .URLByAppendingPathComponent(response.suggestedFilename!)                   
                    	if NSFileManager.defaultManager().fileExistsAtPath(documentsDirUrl.path!) {
                        
                    		try! NSFileManager.defaultManager().removeItemAtURL(documentsDirUrl)
                    	}
                    	
                    	return documentsDirUrl
                	})
        
                   	.progress { (bytesWrite:Int64, totalBytesWrite:Int64, totalBytesExpectedToWrite:Int64) in
                        	
                       	let progressNum:NSNumber = NSNumber(float: Float(Double(totalBytesWrite)/Double(totalBytesExpectedToWrite)))
                       	self.performSelectorOnMainThread(#selector(ViewController.refreshProgress(_:)), 
                       	                      withObject: progressNum, 
                       	                   waitUntilDone: true)
                    	}
                    
                    	.response { (_, _, data:NSData?, error:NSError?) in
                        	
                        if error == nil {
                            
                           	// 删除断点下载缓存文件
                            
                          	let resumeTmpPath = NSSearchPathForDirectoriesInDomains(.CachesDirectory, 
                          	                                                        .UserDomainMask, 
                          	                                                        true)[0] 
                          	                                                      + "/resumeData.tmp"
                            
                          	if NSFileManager.defaultManager().fileExistsAtPath(resumeTmpPath) {
                           		try! NSFileManager.defaultManager().removeItemAtPath(resumeTmpPath)
                          	}
                            	
                       	} else {
                            
                           	// 下载的临时文件不存在处理
                                
                         	if error?.localizedFailureReason == "No such file or directory" {
                                    
        							let resumeTmpPath = NSSearchPathForDirectoriesInDomains(.CachesDirectory, 
        							                                                        .UserDomainMask, 
        							                                                        true)[0]
        							                                                      + "/resumeData.tmp"
                                  
        							if NSFileManager.defaultManager().fileExistsAtPath(resumeTmpPath) {
                                        
        								// 删除断点下载缓存文件,否则继续断点下载会报错
        								try! NSFileManager.defaultManager().removeItemAtPath(resumeTmpPath)
        							}	
        						}
        					}
        				}
            	} else {
                
                	// 重新开始下载
                	
        			self.resumeData = NSData()
                
        			self.downloadRequest = Alamofire.download(.GET, "http://120.25.226.186:32812/resources/videos/minion_01.mp4") 
                	                                         { (temporaryURL:NSURL, response: NSHTTPURLResponse) -> NSURL in
                    
        				let documentsDirUrl:NSURL = NSFileManager.defaultManager()
        				                                         .URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
        				                                         .URLByAppendingPathComponent(response.suggestedFilename!)
        
        					if NSFileManager.defaultManager().fileExistsAtPath(documentsDirUrl.path!) {
                            
        						try! NSFileManager.defaultManager().removeItemAtURL(documentsDirUrl)
        					}
                    
        					return documentsDirUrl
        			}
        
        				.progress { (bytesWrite:Int64, totalBytesWrite:Int64, totalBytesExpectedToWrite:Int64) in
                        
        					let progressNum:NSNumber = NSNumber(float: Float(Double(totalBytesWrite)/Double(totalBytesExpectedToWrite)))
        					self.performSelectorOnMainThread(#selector(ViewController.refreshProgress(_:)), 
        					                      withObject: progressNum, 
        					                   waitUntilDone: true)
        				}
        
        				.response { (_, _, data:NSData?, error:NSError?) in
                        
        					if error == nil {
                            
        					} else {
                            
        						// 停止下载处理
        				
        						if error!.code == NSURLErrorCancelled {
                                
        							if data != nil {
                                    
        								// 意外终止的话,把已下载的数据储存起来
        								self.resumeData = data
                                    
        								let resumeTmpPath = NSSearchPathForDirectoriesInDomains(.CachesDirectory, 
        								                                                        .UserDomainMask, 
        								                                                        true)[0] 
        								                                                      + "/resumeData.tmp"
                                    
        								self.resumeData.writeToFile(resumeTmpPath, atomically: true)
        							}
                                	
        						} else {
                                	
        					}
        				}
        			}
        		}
        
        	// 暂停下载
        	
          		self.downloadRequest.suspend()
         		
        	// 继续下载
        	
          		self.downloadRequest.resume()
           	
        	// 停止下载
        	  
          		self.downloadRequest.cancel()
        

    11、Alamofire 异步 POST 数据请求

    • Swift

      • Alamofire 方式

        	let urlStr:URLStringConvertible = "http://192.168.88.200:8080/MJServer/video"
        	let parameters:[String: AnyObject]? = ["type":"XML"]
        
        	Alamofire.request(.POST, urlStr, parameters: parameters)
        
        		.response { (request:NSURLRequest?, response:NSHTTPURLResponse?, responseData:NSData?, error:NSError?) in
        
        			/*
        				网络请求结束,成功时 error == nil。请求返回的数据存在 responseData 中,为 NSData 格式。
        			*/	
        		}
        
      • Manager 方式

        	// 必须设置为全局的
        	var alamofireManager: Manager!
        
        	let urlStr:URLStringConvertible = "http://192.168.88.200:8080/MJServer/video"
        	let parameters:[String: AnyObject]? = ["type":"XML"]
        
        	self.alamofireManager = Manager(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
        
        	self.alamofireManager.request(.POST, urlStr, parameters: parameters)
            
            	.response { (request:NSURLRequest?, response:NSHTTPURLResponse?, responseData:NSData?, error:NSError?) in
                
                	/*
                    	网络请求结束,成功时 error == nil。请求返回的数据存在 responseData 中,为 NSData 格式。
                 	*/	
            	}
        

    12、Alamofire 文件上传

    • 支持的类型:

      • File
      • Data
      • Stream
      • MultipartFormData
    • Swift

      • Data 形式上传

        	let boundary = "myBoundary"
        
        	// 设置请求头
        	/*
        		upload task 不会在请求头里添加 content-type (上传数据类型)字段,@"myBoundary" 为请求体边界,参数可以随便设置,但需一致
        	*/
        	let headers = ["Content-Type":"multipart/form-data; charset=utf-8; boundary=(boundary)"]
        
        	// 设置请求文件参数
        
            	let formBody = NSMutableData()
            
            	// 参数开始分割线
            	/*
            		每个参数开始前都需要加
            	*/
            	formBody.appendData("--(boundary)".dataUsingEncoding(NSUTF8StringEncoding)!)
            	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
            
            	// 参数
            	/*
            		username 是后台规定的参数名,jhq 是需要添加的参数内容值
            	*/
            	formBody.appendData("Content-Disposition: form-data; name="("username")"
        
        ("jhq")"
            	        .dataUsingEncoding(NSUTF8StringEncoding)!)
            	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
            
            	// 文件开始分割线
            	/*
            		每个文件开始前都需要加
            	*/
            	formBody.appendData("--(boundary)".dataUsingEncoding(NSUTF8StringEncoding)!)
            	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
            
            	// 文件参数名
            	/*
            		file 是后台规定的参数名,test.mp4 为上传后服务器端文件名称
            	*/
            	formBody.appendData("Content-Disposition: form-data; name="("file")"; filename="("test.mp4")""
            	        .dataUsingEncoding(NSUTF8StringEncoding)!)
            	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
            
            	// 文件的类型
            	formBody.appendData("Content-Type: mp4".dataUsingEncoding(NSUTF8StringEncoding)!)
            	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
            	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
            
            	// 待上传文件数据
            	/*
            		本地待上传的文件路径
            	*/
          		formBody.appendData(NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("minion", ofType: "mp4")!)!)
            	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
            
            	// 结束分割线标记
            	formBody.appendData("--(boundary)--".dataUsingEncoding(NSUTF8StringEncoding)!)
            	formBody.appendData("
        ".dataUsingEncoding(NSUTF8StringEncoding)!)
        
        	Alamofire.upload(.POST, "http://192.168.88.200:8080/MJServer/upload", headers: headers, data: formBody)
            
            	.progress { (bytesLoad:Int64, totalBytesLoad:Int64, totalBytesExpectedToLoad:Int64) in
                
                	/*
                    	监听文件上传进度,此 block 在子线程中执行。
                 	*/
                
                	let progressNum:NSNumber = NSNumber(float: Float(Double(totalBytesLoad)/Double(totalBytesExpectedToLoad)))
                	self.performSelectorOnMainThread(#selector(ViewController.refreshProgress(_:)), withObject: progressNum, waitUntilDone: true)
            	}
            
            	.response { (_, _, responseData:NSData?, error:NSError?) in
                
                	/*
                    	网络请求结束。
                 	*/	
            	}
        
      • MultipartFormData 形式上传

        	Alamofire.upload(.POST, "http://192.168.88.200:8080/MJServer/upload", 
        	                        multipartFormData: { (formData:MultipartFormData) in
            
            	/*
                	添加参数。第一个参数是需要添加的参数内容值,第二个是后台规定的参数名。
             
                	设置上传的文件。第一个参数是需要上传的文件路径,第二个是后台规定的参数名,第三个是上传后服务器端文件名称,第四个是文件类型。
             	*/
            
            	// 添加参数
            
                	formData.appendBodyPart(data: "jhq".dataUsingEncoding(NSUTF8StringEncoding)!, name: "username")
            
            	// 指定文件路径形式上传
            
                	let fileUrl = NSBundle.mainBundle().URLForResource("HQ_0005", withExtension: "jpg")!
            
                	formData.appendBodyPart(fileURL: fileUrl, name: "file", fileName: "test.png", mimeType: "image/jpeg")
            
            	// 指定文件数据形式上传
            
                	let fileData = NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("minion", ofType: "mp4")!)
            
                	formData.appendBodyPart(data: fileData!, name: "file", fileName: "test.mp4", mimeType: "mp4")
            
        	}) { (encodingResult:Manager.MultipartFormDataEncodingResult) in
            
            	/*
                	数据编码完成。
             	*/
            
            	switch encodingResult {
                
                	// 编码成功
                	case .Success(let uploadRequest, _, _):
        
                    	uploadRequest
        
        					.progress { (bytesLoad:Int64, totalBytesLoad:Int64, totalBytesExpectedToLoad:Int64) in
                            
                          	/*
                           		监听文件上传进度,此 block 在子线程中执行。
                           	*/
                            
                         	let progressNum:NSNumber = NSNumber(float: Float(Double(totalBytesLoad)/Double(totalBytesExpectedToLoad)))
                         	self.performSelectorOnMainThread(#selector(ViewController.refreshProgress(_:)), 
                         	                      withObject: progressNum, 
                         	                   waitUntilDone: true)
                       	}
                        
                       	.response { (_, _, responseData:NSData?, error:NSError?) in
                            
                         	/*
                             	网络请求结束。
                          	*/	
                        }
                
                	// 编码失败
                	case .Failure(let error):
                    	
                    	print(error)
            	}
        	}
        
  • 相关阅读:
    vs2015 停 在 update kb2999226 一直不动
    修复vs2012出现 “无法找到包源”的错误
    forward 和redirect的区别
    软件测试分类
    centos7安装HTTPS协议
    php抓取网页特定div区块及图片,从简单入手
    nginx报 File not found 错误
    关于端口
    调试技巧:让断点停在for循环中的 i 为某个值得时候
    an AC a day keeps the WA away ~
  • 原文地址:https://www.cnblogs.com/QianChia/p/5768547.html
Copyright © 2020-2023  润新知