网络通信
1、判断网络连接情况
开源第三方类Swift-Reachability实现判断网络情况,支持3G和WiFi检测。
// MARK: - 检测网络连接情况 @IBOutlet var typeLabel: UILabel! @IBAction func checkButtonUpinside(sender: UIButton) { let reachability = Reachability.reachabilityForInternetConnection() reachability?.stopNotifier() let statusType:Reachability.NetworkStatus = (reachability?.currentReachabilityStatus)! if statusType == Reachability.NetworkStatus.ReachableViaWWAN { typeLabel.text = "连接类型:移动网络4G" } else if statusType == Reachability.NetworkStatus.ReachableViaWiFi { typeLabel.text = "连接类型:WiFi" } else if statusType == Reachability.NetworkStatus.NotReachable { typeLabel.text = "连接类型:没有网络连接" } }
2、网络请求JSON解析
使用NSURLConnection实现HTTP通信方式,NSURLConnection提供了异步请求和同步请求两种通信方式。同步请求数据容易造成主线程的阻塞,通常在请求大数据或者网络状态不好的情况下不建议使用。
建立通信的步骤如下:
1)创建NSURL;
2)创建Request对象;
3)创建NSURLConnection连接。
<1>同步请求数据方式
1 // MARK: - 同步请求 2 func httpSynchronousRequest() 3 { 4 //创建NSURL对象 5 let url:NSURL! = NSURL(string: "http://swift.leadingdo.com/weather.json") 6 7 //创建请求对象 8 let urlRequest : NSURLRequest = NSURLRequest(URL: url) 9 10 11 //发出请求 12 NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: { (response:NSURLResponse?, data:NSData?, error:NSError?) -> Void in 13 14 15 if (error != nil) 16 { 17 print(error?.code) 18 print(error?.description) 19 }else 20 { 21 let jsonString = NSString(data: data!, encoding: NSUTF8StringEncoding) 22 23 print(jsonString) 24 } 25 26 }) 27 28 }
<2>异步请求方式
1 // MARK: - 异步请求 2 func httpAsynchronousRequest() 3 { 4 //创建NSURL对象 5 let url:NSURL! = NSURL(string: "http://swift.leadingdo.com/weather.json") 6 7 //创建请求对象 8 let urlRequest : NSURLRequest = NSURLRequest(URL: url) 9 10 //网络连接对象 11 let conn : NSURLConnection? = NSURLConnection(request: urlRequest, delegate: self) 12 13 conn?.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes) 14 15 //执行 16 conn?.start() 17 }
1 // MARK: - NSURLConnectionDataDelegate 2 func connection(connection: NSURLConnection, willSendRequest request: NSURLRequest, redirectResponse response: NSURLResponse?) -> NSURLRequest? 3 { 4 //将要发送请求 5 return request 6 } 7 8 func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) 9 { 10 //接收响应 11 } 12 13 //接收到服务器传输数据的时候调用,此方法根据数据大小执行若干次 14 var jsonData:NSMutableData = NSMutableData()
15 func connection(connection: NSURLConnection, didReceiveData data: NSData) 16 { 17 //收到数据 18 self.jsonData.appendData(data) 19 } 20 21 func connection(connection: NSURLConnection, needNewBodyStream request: NSURLRequest) -> NSInputStream? 22 { 23 //需要新的内容流 24 return request.HTTPBodyStream 25 } 26 27 func connection(connection: NSURLConnection, didSendBodyData bytesWritten: Int, totalBytesWritten: Int, totalBytesExpectedToWrite: Int) 28 { 29 //发送数据请求 30 } 31 32 func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse? 33 { 34 //缓存响应 35 return cachedResponse 36 } 37 38 func connectionDidFinishLoading(connection: NSURLConnection) 39 { 40 //请求结束,解析jsonData数据流。 41 let jsonString = NSString(data: self.jsonData, encoding: NSUTF8StringEncoding) 42 43 print(jsonString) 44 45 do { 46 if let dic:Dictionary<String,AnyObject> = try NSJSONSerialization.JSONObjectWithData(self.jsonData, options: NSJSONReadingOptions()) as? Dictionary<String,AnyObject> 47 { 48 49 print(dic) 50 51 if let weatherinfoDic:Dictionary<String,AnyObject> = dic["weatherinfo"] as? Dictionary<String,AnyObject> 52 { 53 if let city = weatherinfoDic["city"] as? String{ 54 print(city) 55 } 56 57 if let WD = weatherinfoDic["WD"] as? String{ 58 print(WD) 59 } 60 61 if let WS = weatherinfoDic["WS"] as? String{ 62 print(WS) 63 } 64 } 65 } 66 } 67 catch let error as NSError { 68 print("失败:\(error)")//如果失败,error 会返回错误信息 69 } 70 }
3、同步Get方式
对于Get方式,服务器端用Request.QueryString获取变量的值,对于Post方式,服务器端用Request.From获取提交的数据。
在做数据查询的时,建议用Get方式;在进行数据的添加、修改和删除时,建议用Post方式。
// MARK: - 同步Get方式 func synchronousGet() { //创建NSURL对象 let url:NSURL! = NSURL(string: "http://swift.leadingdo.com/weather.json") //创建请求对象 let urlRequest : NSURLRequest = NSURLRequest(URL: url, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 10) //响应对象 var response:NSURLResponse? //发出请求 do { let received = try NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse: &response) let jsonString = NSString(data: received, encoding: NSUTF8StringEncoding) print(jsonString) } catch let error as NSError { print("失败:\(error)")//如果失败,error 会返回错误信息 } }
public enum NSURLRequestCachePolicy : UInt { case UseProtocolCachePolicy //基础策略 case ReloadIgnoringLocalCacheData //忽略本地缓存 case ReloadIgnoringLocalAndRemoteCacheData // 无视任何缓存策略,无论是本地还是远程的,总是从原地址重新下载 case ReturnCacheDataElseLoad //首先使用缓存,如果没有本地缓存,才从原地址下载 case ReturnCacheDataDontLoad //使用本地缓存,从不下载,如果本地没有缓存,则请求失败,此策略多用于离线操作。 case ReloadRevalidatingCacheData // 如果本地缓存是有效的则不下载,其他任何情况都从原地址重新下载 }
4、异步Get请求方式
// MARK: - 异步Get方式 func asynchronousGet() { //创建NSURL对象 let url:NSURL! = NSURL(string: "http://swift.leadingdo.com/weather.json") //创建请求对象 let urlRequest : NSURLRequest = NSURLRequest(URL: url, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 10) //连接服务器 let connection = NSURLConnection(request: urlRequest, delegate: self) print(connection) }
主要实现下面的两个异步请求代理方法NSURLConnectionDataDelegate,来接收相关数据。
func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) { //接收响应 } //接收到服务器传输数据的时候调用,此方法根据数据大小执行若干次 var jsonData:NSMutableData = NSMutableData() func connection(connection: NSURLConnection, didReceiveData data: NSData) { //收到数据 self.jsonData.appendData(data) }
5、同步post请求如下:
1 // MARK: - 同步Post方式 2 func synchronousPost() 3 { 4 //创建NSURL对象 5 let url:NSURL! = NSURL(string: "http://swift.leadingdo.com/weather.json") 6 7 //创建请求对象 8 let request : NSMutableURLRequest = NSMutableURLRequest(URL: url, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 10) 9 10 request.HTTPMethod = "POST"//设置请求方式为POST,默认为GET 11 12 let str:String = "type=focus-c";//设置参数 13 let data:NSData = str.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! 14 request.HTTPBody = data; 15 16 //响应对象 17 var response:NSURLResponse? 18 19 //发出请求 20 do 21 { 22 let received = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response) 23 let jsonString = NSString(data: received, encoding: NSUTF8StringEncoding) 24 25 print(jsonString) 26 } 27 catch let error as NSError { 28 print("失败:\(error)")//如果失败,error 会返回错误信息 29 } 30 }
6、异步post请求方式
1 // MARK: - 异步Post方式 2 func asynchronousPost() 3 { 4 //创建NSURL对象 5 let url:NSURL! = NSURL(string: "http://swift.leadingdo.com/weather.json") 6 7 //创建请求对象 8 let request : NSMutableURLRequest = NSMutableURLRequest(URL: url, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 10) 9 10 request.HTTPMethod = "POST"//设置请求方式为POST,默认为GET 11 12 let str:String = "type=focus-c";//设置参数 13 let data:NSData = str.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! 14 request.HTTPBody = data; 15 16 //连接服务器 17 let connection = NSURLConnection(request: request, delegate: self) 18 }
7、NSURLSession加载数据、下载、上传
NSURLSession类支持三种类型任务:加载数据、下载和上传。
Data Task用于加载数据,使用全局的sharedSession()和func dataTaskWithRequest(request: NSURLRequest, completionHandler:((NSData!, NSURLRequesse!, NSError!)-> Void?)-> NSURLSessionDataTask方法创建。
1)加载数据
// MARK: - /* 使用NSURLSessionDataTask加载数据 */ func sessionLoadData() { //创建NSURL对象 let url:NSURL! = NSURL(string: "http://swift.leadingdo.com/weather.json") //创建请求对象 let request : NSURLRequest = NSURLRequest(URL: url) let session = NSURLSession.sharedSession() let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in //返回错误信息情况 if (error != nil) { print(error?.code) print(error?.description) }else { let jsonString = NSString(data: data!, encoding: NSUTF8StringEncoding) print(jsonString) } }) as NSURLSessionTask //使用resume方法启动任务 dataTask.resume() }
2)下载文件任务
1 // MARK: - /* 使用NSURLSessionDataTask下载文件 ---- 简单下载,不需要知道下载进度 */ 2 func sessionSimpleDownload() 3 { 4 //下载地址 5 let url = NSURL(string: "http://swift.leadingdo.com/SwiftClassIcon.jpg") 6 //请求 7 let request = NSURLRequest(URL: url!) 8 //连接 9 let session = NSURLSession.sharedSession() 10 //下载任务 11 let downloadTask = session.downloadTaskWithRequest(request, completionHandler: { (location:NSURL?,response:NSURLResponse?, error:NSError?) -> Void in 12 13 // 输出下载文件原来的存放目录 14 print("location: \(location)") 15 16 //location位置转换 17 let locationPath = location?.path 18 19 //拷贝到我们自己目录中 20 let documents:String = NSHomeDirectory() + "/Documents/1.png" 21 22 // 创建文件管理器 23 let fileManager :NSFileManager = NSFileManager.defaultManager() 24 25 do 26 { 27 try fileManager.moveItemAtPath(locationPath!, toPath: documents) 28 } 29 catch let error as NSError { 30 print("失败:\(error)")//如果失败,error 会返回错误信息 31 } 32 print("location: \(documents)") 33 }) 34 35 //使用resume方法启动任务 36 downloadTask.resume() 37 }
// MARK: - /* 使用NSURLSessionDataTask下载文件 ---- 获取进度 */ //创建一个下载模式--单利实现,自定义NSURLSession对象方法如下: func currentSession()->NSURLSession{ var predicate:dispatch_once_t = 0 var currentSession:NSURLSession? = nil dispatch_once(&predicate,{ let config = NSURLSessionConfiguration.defaultSessionConfiguration() currentSession = NSURLSession(configuration: config, delegate: self, delegateQueue: nil) } ) return currentSession! }
下载方法代码如下:
func sessionSeniorDownload() { //下载地址 let url = NSURL(string: "http://swift.leadingdo.com/SwiftClassIcon.jpg") //请求 let request = NSURLRequest(URL: url!) //连接 let session = currentSession() as NSURLSession //下载任务 let downloadTask = session.downloadTaskWithRequest(request) //使用resume方法启动任务 downloadTask.resume() }
实现NSURLSessionDownloadDelegate代理方法,来监听下载进度。
// MARK: - NSURLSessionDownloadDelegate func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) { //下载结束 print("下载结束") } func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { //获取进度 let written:CGFloat = (CGFloat)(bytesWritten) let total:CGFloat = (CGFloat)(totalBytesExpectedToWrite) let pro:CGFloat = written / total print("下按进度:\(pro)") } func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) { //下载偏移,主要用于暂停续传 }
下载完成后,下载的文件位于tmp目录下,所以需要将文件保存到持久化的目录下保存,拷贝到自己定义的目录下方便以后使用。
// 输出下载文件原来的存放目录 print("location: \(location)") //location位置转换 let locationPath = location?.path //拷贝到我们自己目录中 let documents:String = NSHomeDirectory() + "/Documents/1.png" // 创建文件管理器 let fileManager :NSFileManager = NSFileManager.defaultManager() do { try fileManager.moveItemAtPath(locationPath!, toPath: documents) } catch let error as NSError { print("失败:\(error)")//如果失败,error 会返回错误信息 } print("location: \(documents)")
3)上传文件任务
1 // MARK: - /* 使用NSURLSessionDataTask上传文件 */ 2 func sessionUpload() 3 { 4 //上传的位置地址 5 let url = NSURL(string: "http://swift.leadingdo.com/data/") 6 7 //请求 8 let request = NSURLRequest(URL: url!) 9 10 //连接 11 let session = NSURLSession.sharedSession() 12 13 //上传数据流 14 let documents:String = NSHomeDirectory() + "/Documents/1.png" 15 let imgData = NSData(contentsOfFile: documents) 16 17 let uploadTask = session.uploadTaskWithRequest(request, fromData: imgData, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in 18 19 //上传完毕之后判断 20 print("上传完毕") 21 }) 22 23 //使用resume方法启动任务 24 uploadTask.resume() 25 }