THE SWIFT CODE之网络编程 NSURLSESSION

NSURLSession,是IOS中一种封装性的网络请求功能(当然是我的理解),他以委托的形式来处理相关的网络请求,我们从几个方面来看看他的请求形式.

1.基本的网络请求

2.数据接收处理

3.后台处理请求

4.上传数据请求

 

基本的网络请求,通过NSURLSession来处理最简单的网络请求,首先是通过NSURLSessionConfiguration来创建基本的请求配置.这里有三种方式创建

backgroundSessionConfigurationWithIdentifier 后台处理配置

ephemeralSessionConfiguration 这个是基于RAM的方式处理配置,数据时临时性的

defaultSessionConfiguration 这个是默认配置

创建好配置后,我们通过timeoutIntervalForRequest来处理连接超时的情况,这个时间可以自己随自己的需求设定,我一般是设定在20s左右,然后通过NSURLSession的构造函数,来创建session,将处理委托给本身这个类,当然自己也可以重新创建一个新类来处理.接着就是调用dataTaskWithURL来处理请求,记得在请求处理完后,释放session,这里调用finishTashsAndInvalidate这个方法.在下面的代码里面我们通过NSFileManager来讲数据保存在缓存目录下.

在类中我们创建了displayAlertWithTitle方法,这个主要是用来弹出显示请求数据的(弹出框的简单应用),最后调用resume方法,执行请求操作.

import UIKit

class ViewController: UIViewController,NSURLSessionDelegate,NSURLSessionDataDelegate {
    
    var session:NSURLSession!
    
    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.wutongwei.com")
        
        
        let task = session.dataTaskWithURL(url!, completionHandler: { (
            data, response, error) -> Void in
            
            
            let str = NSString(data: data, encoding: NSUTF8StringEncoding)
            println("Done!")
            
            self.session.finishTasksAndInvalidate() //确保执行完成后,释放session
            
            
            if error == nil {
                
                let manager = NSFileManager()
                
                //
                var error:NSError?
                var destinationPath = manager.URLForDirectory(NSSearchPathDirectory.CachesDirectory, inDomain: NSSearchPathDomainMask.UserDomainMask, appropriateForURL: url, create: true, error: &error)!
                //
                let componenetsOfUrl = url?.absoluteString!.componentsSeparatedByString("/")
                let index = componenetsOfUrl!.count - 1
                let fileNameFromUrl = componenetsOfUrl![index]
                
                destinationPath = destinationPath.URLByAppendingPathComponent(fileNameFromUrl)
                
                
                //
                manager.moveItemAtURL(url!, toURL: destinationPath, error: nil)
                
                let message = "保存下载数据到 = \(destinationPath)"
                
                self.displayAlertWithTitle("Success", message: message)
                
                
            }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)
    }
    
    
    ///
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
}

 

下面我们来通过委托形式处理数据,主要是实现委托协议的一些相关方法.这里我们实现了两个URLSession方法包含参数didReceiveData和另外一个包含参数didCompleteWithError 

didReceiveData 处理请求时的数据,我们在类中定义了NSMutableData类型的变量,这个变量主要用来接收didReceiveData这个方法传递过来的数据

didCompleteWithError 在处理完请求后响应的事件.

在这里在说明两个方法didReceiveData和didReceiveResponse,两个只能存在一个,didReceiveResponse高于didReceiveData,前者有的话,后者就不能执行

import UIKit

class ViewController2:UIViewController,NSURLSessionDelegate,NSURLSessionDataDelegate{
    
    var mutableData:NSMutableData = NSMutableData()
    
    var session:NSURLSession?
    
    override init() {
        
        super.init()
        
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        
        session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
        
    }
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        
    }
    
    required init(coder aDecoder: NSCoder) {
    
        super.init(coder: aDecoder)
        
   }
    
    override func viewDidAppear(animated: Bool) {
        
        let url:NSURL? = NSURL(string: "http://www.wutongwei.com")
        
        let task:NSURLSessionDataTask = session!.dataTaskWithURL(url!, completionHandler: nil)
        
        task.start()
        
    }
    
    
    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)
    }

    NSURLSessionDataDelegate
    
    //完成下载,下载错误,出错了,其他方法不会执行
    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        
        println("didCompleteWithError")
        
        session.finishTasksAndInvalidate()
        
        dispatch_async( dispatch_get_main_queue()) { () -> Void in
            
            var message = "完成下载数据"
            
            if error != nil{
                message = "下载内容失败"
            }
            self.displayAlertWithTitle("完成", message: message)
            
            NSLog(self.mutableData.description)
            
        }
        
    }
    
    
    
    //didReceiveData 和 didReceiveResponse ,两个只能存在一个,didReceiveResponse高于didReceiveData,前者有的话,后者就不能执行
    //数据接收
    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
        
        println("didReceiveData")
        
        data.enumerateByteRangesUsingBlock { (point:UnsafePointer<Void>, range:NSRange, stop:UnsafeMutablePointer<ObjCBool>) -> Void in
            
            let newData = NSData(bytes: point, length: range.length)
            
            self.mutableData.appendData(newData)
            
        }
 
    }
    
//    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
//        
//        println("didReceiveResponse,\(response),\n \(dataTask)")
//        
//    }
    
 

    
}

 

接着我们来看看后台委托处理的方式.这里我们加入了NSURLSessionDelegate,NSURLSessionDownloadDelegate,NSURLSessionTaskDelegate 
这几个委托协议.然后类中我们声明了一个识别签名,这个签名存储在NSUserDefaults中,因为创建后台请求需要一个识别签名,来管理.其实请求处理方式跟上面差不多,知识执行的委托方法不一样,代码中我已经写上了相关的输出说明,大家调试一下就明白了

import UIKit

class ViewController3:UIViewController,NSURLSessionDelegate,NSURLSessionDownloadDelegate,NSURLSessionTaskDelegate {
    
    var session:NSURLSession!
    
    var configidentifier:String{
       
        let userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
        let key  = "configidenti"
        
         let preval = userDefaults.stringForKey(key)
        
        if let thepreval = preval {
            return preval!
        }else{
            let newval = NSDate().description
            userDefaults.setObject(newval, forKey: key)
            userDefaults.synchronize()
            return newval
        }
        
    
    }
    
    override init() {
        super.init()
        let config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(self.configidentifier)
        config.timeoutIntervalForRequest = 15
        
        session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
    }
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
   override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }
    
    
    //
    
    override func viewDidAppear(animated: Bool) {
    
          super.viewDidAppear(animated)
        
          let url = NSURL(string: "http://www.wutongwei.com")
        
           let task = session.downloadTaskWithURL(url!)
        
           task.start()
        
    }
    
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        
        NSLog("接收数据")
        
    }
    
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
        
        NSLog("下载完成")
    }
    
    
    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        
        NSLog("任务完成")
        
        session.finishTasksAndInvalidate()
    }
    
    //
    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)
    }
    
    
}

最后我们来看一下怎么上传数据.相关的基本配置跟上面的类似,不同的是,这里需要创建NSMutableURLRequest请求对象,然后调用session的uploadTaskWithRequest进行上传请求,其实也不是那么难!

import UIKit

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)
    }

    
    override init() {
        super.init()
        
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        config.timeoutIntervalForRequest  = 15
        
        session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
        
    }
    
    required init(coder aDecoder: NSCoder) {
        
        super.init(coder: aDecoder)
    }
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }
    
    
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        
        let datatoup = "Hello World".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
        
        let url = NSURL(string: "http://www.baidu.com")
        
        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)
            
        })
        
    }
    
}

这里说明一下这个task方法,我这里扩展了NSURLSessionTask,因为使用resume来执行任务有点怪怪的,可能还没习惯.

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

 

转载于:https://my.oschina.net/ldm95/blog/685501

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值