深谙iOS网络编程之Http NSURLSession(下)

深谙iOS网络编程之Http NSURLSession(下)_第1张图片
革码者基地

1.前言

  • 此文章将记录Http请求之NSURLSession用法。至于什么是Http,可参考深谙iOS网络编程之Http真相揭秘(上)
  • 由于在iOS9.0之后,NSURLConnection被废弃,苹果推荐使用NSURLSession来替换NSURLConnection完成网路请求相关操作,所以本文不再涉及NSURLConnection用法。

2.NSURLSession

简单:NSURLSession的使用非常简单,先根据会话对象创建一个请求Task,然后执行该Task即可。

抽象:NSURLSessionTask本身是一个抽象类,在使用的时候,通常是根据具体的需求使用它的几个子类。关系如下:

深谙iOS网络编程之Http NSURLSession(下)_第2张图片
革码者基地

一、发送GET请求
  使用NSURLSession发送GET请求的方法整个过程如下:
    1)确定请求路径,GET请求参数直接跟在URL后面
    2)创建请求对象(默认包含了请求头和请求方法【GET】),可配置
    3)创建会话对象(NSURLSession),可配置
    4)根据会话对象创建请求任务(NSURLSessionDataTask)
    5)执行Task
    6)当得到服务器返回的响应后,解析数据(XML|JSON|HTTP)

//普通的HTTP get请求
    func getRequest(){
        // 获取Url --- 这个是我获取的天气预报接口
        let url:NSURL = NSURL(string: "http://aqicn.org/publishingdata/json")!
        // 转换为requset
        let requets:NSURLRequest = NSURLRequest(URL: url)
        //NSURLSession 对象都由一个 NSURLSessionConfiguration 对象来进行初始化,后者指定了刚才提到的那些策略以及一些用来增强移动设备上性能的新选项
        let configuration:NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()

        //backgroundSessionConfigurationWithIdentifier 后台处理配置
        //ephemeralSessionConfiguration 这个是基于RAM的方式处理配置,数据时临时性的
        //defaultSessionConfiguration 这个是默认配置

        let session:NSURLSession = NSURLSession(configuration: configuration)
        
        //NSURLSessionTask负责处理数据的加载以及文件和数据在客户端与服务端之间的上传和下载,NSURLSessionTask 与 NSURLConnection 最大的相似之处在于它也负责数据的加载,最大的不同之处在于所有的 task 共享其创造者 NSURLSession 这一公共委托者(common delegate)
        let task:NSURLSessionDataTask = session.dataTaskWithRequest(requets, completionHandler: {
            (data:NSData?,response:NSURLResponse?,error:NSError?)->Void in
            if error == nil{
                do{                    
                    let responseData = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! NSArray       
                    print(responseData)
                    dispatch_async(dispatch_get_main_queue(), { () -> Void in
                        self.dataLabel.text = responseData.firstObject!["cityName"]! as? String
                    })                    
                }catch{
                    
                }
            }
        })
        // 启动任务
        task.resume()
    }
//带header的HTTP get 请求
    @IBAction func getRequestWithHeader(sender: AnyObject) {
        
        let url:NSURL = NSURL(string: "http://apis.baidu.com/heweather/pro/weather?city=beijing")!
        
        let request:NSMutableURLRequest = NSMutableURLRequest(URL:url)
        
        request.HTTPMethod = "GET"
        // 请求的Header
        request.addValue("a566eb03378211f7dc9ff15ca78c2d93", forHTTPHeaderField: "apikey")
        
        let configuration:NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session:NSURLSession = NSURLSession(configuration: configuration)

        let task:NSURLSessionDataTask = session.dataTaskWithRequest(request, completionHandler: {
            (data:NSData?,response:NSURLResponse?,error:NSError?)->Void in
            if error == nil{
                do{
                    let responseData:NSDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! NSDictionary
                    print("普通带头与参数的GET请求 --- > \(responseData)")
                    
                }catch{
                    
                }
            }
        })
        task.resume()
    }
//get请求实战应用:写入文件。
    override func viewDidLoad() {
        super.viewDidLoad()
        //let config = NSURLSessionConfiguration.backgroundSessionConfiguration("back")//不赞成使用
        //let config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("back")//委托中不能使用,使用系统处理下载,就算APP没有运行了,也可以实现
        //let config = NSURLSessionConfiguration.ephemeralSessionConfiguration();//这个是临时数据下载,适用于小数据下载
       
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()//默认配置
        config.timeoutIntervalForRequest = 15 //连接超时时间
        
        session = NSURLSession(configuration: config, delegate: self, delegateQueue:nil)//队列中,如果想要程序在主线程中执行,可以使用NSOperationQueue.mainQueue()
        
        let url = NSURL(string: "http://www.jianshu.com/p/e89f4b40bd85")
        let task = session.dataTaskWithURL(url!) { (data, response, error) -> Void in
            if (error == nil){
                
                let str = NSString(data: data!, encoding: NSUTF8StringEncoding)
                print("Done!")
               
                self.session.finishTasksAndInvalidate() //确保执行完成后,释放session
   
                let manager = NSFileManager.defaultManager()                
                do{
                    var destinationPath = try manager.URLForDirectory(.CachesDirectory, inDomain: .UserDomainMask, appropriateForURL: url, create: true)
                    
//                    获取//符号后面的string
                    let componenetsOfUrl = url?.absoluteString.componentsSeparatedByString("/")
                    let index = componenetsOfUrl!.count - 1
                    let fileNameFromUrl = componenetsOfUrl![index]+".text"
                    
                    destinationPath = destinationPath.URLByAppendingPathComponent(fileNameFromUrl)                    
                    try str?.writeToURL(destinationPath, atomically: true, encoding: NSUTF8StringEncoding)
                    let message = "保存下载数据到 = \(destinationPath)"             
                    self.displayAlertWithTitle("Success", message: message)
                    print(message)
                }catch{
                   print("error")
                }             
            }else{
                self.displayAlertWithTitle("Error", message: "不能下载这数据,一个错误抛出")
            }
        }
        task.resume()       
    }
   
    func displayAlertWithTitle(title:String,message:String){        
        let controller = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        controller.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
        presentViewController(controller, animated: true, completion: nil)
    }
//get请求实战应用:后台下载处理
import UIKit

extension NSURLSessionTask{
    func start(){
        self.resume()
    }
}

class ViewController3:UIViewController,NSURLSessionDelegate,NSURLSessionDownloadDelegate,NSURLSessionTaskDelegate {
    
    var session:NSURLSession!
    
    var configidentifier:String{
        
        let userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
        let key  = "time"
        
        let times = userDefaults.stringForKey(key)
        
        if let thetime = times {
            return thetime
        }else{
            let newtime = NSDate().description
            userDefaults.setObject(newtime, forKey: key)
            userDefaults.synchronize()
            return newtime
        }
    }
    
  
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }
   
    
    override func viewDidAppear(animated: Bool) {
        
        super.viewDidAppear(animated)
        
        let config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(self.configidentifier)
        config.timeoutIntervalForRequest = 15
        
        session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
        
        let url = NSURL(string: "http://www.jianshu.com/p/e89f4b40bd85")
        
        let task = session.downloadTaskWithURL(url!)
        
        task.start()
        
    }
    
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        print(downloadTask.response)
        let progress = totalBytesWritten / totalBytesExpectedToWrite
        print(bytesWritten)
        print(totalBytesWritten)
        print(totalBytesExpectedToWrite)//如果服务器未返回总长度,这里就显示-1
        print(progress)
        NSLog("接收数据")
       
    }
    
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
        do{
           
            // 将临时文件剪切或者复制其他文件夹才能看到
           let fileManager = NSFileManager.defaultManager()
           let cachePath = try fileManager.URLForDirectory(.CachesDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
           let saveFileName = (cachePath.path)! + "/" + (downloadTask.response?.suggestedFilename)!
           try fileManager.moveItemAtPath(location.path!, toPath: saveFileName)
           NSLog("下载完成")
        }catch{
            
        }
    }
    
    
    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        
        NSLog("任务完成")
        
        session.finishTasksAndInvalidate()
    }

二、发送POST请求
    使用NSURLSession发送POST请求的方法整个过程如下:
    1)确定请求路径(一般由公司的后台开发人员以接口文档的方式提供)
    2)创建可变的请求对象(因为需要修改),此步骤不可以省略
    3)修改请求方法为POST
    4)设置请求体,把参数转换为二进制数据并设置请求体
    5)创建会话对象(NSURLSession)
    6)根据会话对象创建请求任务(NSURLSessionDataTask)
    7)执行Task
    8)当得到服务器返回的响应后,解析数据(XML|JSON|HTTP)

//普通的HTTP Post请求
    func postRequest(){
        let request = NSMutableURLRequest(URL: NSURL(string: "http://120.25.226.186:32812/login")!)
        // 这块就是区别啦,其实也差不多
        request.HTTPMethod = "POST"
        let postString = "username=520it&pwd=520it&type=JSON"
        request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
        
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {
            (data:NSData?,response:NSURLResponse?,error:NSError?)->Void in
            if error == nil{
                do{
//解析方式1
                    let responseString = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! NSDictionary
                 
                     print("Post --- > \(responseString)")
                    let result = responseString["success"]?.dataUsingEncoding(NSUTF8StringEncoding)
                    let result1 = NSString(data: result!, encoding:NSUTF8StringEncoding )
                    print(result1)
// 解析方式2
                    let responseString2 = NSString(data: data!, encoding: NSUTF8StringEncoding)
                    print("Post --- > \(responseString2)")
                }catch{
                    print("have catch")
                }
            }    
        })
        task.resume()
    }
//post请求实战应用:上传
class ViewController4:UIViewController,NSURLSessionDelegate,NSURLSessionDataDelegate{ 
    var session:NSURLSession!    
    func displayAlertWithTitle(title:String,message:String){        
        let controller:UIAlertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)        
        controller.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))        
        presentViewController(controller, animated: true, completion: nil)
    } 
    required init(coder aDecoder: NSCoder) {       
        super.init(coder: aDecoder)!
    }
 
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        
        
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        config.timeoutIntervalForRequest  = 15
        
        session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
        let datatoup = "Hello World".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
        
        let url = NSURL(string: "http://www.jianshu.com/p/e89f4b40bd85")
        
        let request = NSMutableURLRequest(URL: url!)
        
        request.HTTPMethod = "POST"
        
        let task = session.uploadTaskWithRequest(request, fromData: datatoup!)
        
        task.start()
        
    }
    
    
    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        
        session.finishTasksAndInvalidate()
        
        NSLog("错误 = \(error)")
        
        
        dispatch_async(dispatch_get_main_queue(), {[weak self] () -> Void in
            
            var message = "完成上传数据"
            
            if error != nil {
                message = "上传内容失败"
            }            
            self?.displayAlertWithTitle("信息", message: message)            
            })        
    }    
}

至此,文章已经记录了HTTP中的GET和POST请求的基本应用。希望对学习网络编程的码儿有所帮助。

你可能感兴趣的:(深谙iOS网络编程之Http NSURLSession(下))