Swift2网络操作和异常处理

相信写过Swift的人应该都知道Alamofire,它是AFNetworking的Swift版本,同一个作者写的。之前在项目中我也一直使用Alamofire,但是升级到Xcode7之后旧版的Alamofire不能用了,最新版的又只支持iOS8之后的系统,而公司项目还得兼容iOS7,所以接下来不打算用它了。

我的需求比较简单,只要能发送GET请求获取数据以及发送POST请求提交数据就好了,大致看了一下Alamofire的源码又上网查了点资料之后,花了不到半天写了几个简单的函数,项目又能正常跑起来了。

iOS7之后的系统都支持NSURLSession,我们就把它稍微封装一下好了。

funcgetDataFrom(urlString:String,method:HTTPMethod,parameter:[String:String]?,completionHandler:Callback)throws{//letconfig=NSURLSessionConfiguration.defaultSessionConfiguration()
//config.timeoutIntervalForRequest=20
//letsession=NSURLSession(configuration:config)
guardleturl=NSURL(string:urlString)else{
throwError.InvalidURL
}letsession=NSURLSession.sharedSession()letrequest=NSMutableURLRequest(URL:url)
request.HTTPMethod=method.rawValueswitchmethod{case.POST://如果参数为nil或者字典中没有元素,则抛出异常
guardletparam=parameterelse{
throwError.NoParameter
}
guardparam.isEmptyelse{
throwError.NoParameter
}

request.addValue("application/json",forHTTPHeaderField:"Content-Type")
request.addValue("application/json",forHTTPHeaderField:"Accept")do{
request.HTTPBody=tryNSJSONSerialization.dataWithJSONObject(param,options:[])
}catch{print(error)
}case.GET:break
}lettask=session.dataTaskWithRequest(request){data,response,errorin
guardletresult=datawhereerror==nilelse{
printLog("nodata:\(error)")return
}

completionHandler(data:result)
}//启动
task.resume()

}

这个函数声明的时候在->前加了一个throws,表明这个函数是可以抛出异常的。其实以往iOS开发比较推崇"Let it crash!"的哲学,不过Swift一直很强调安全性,Apple显然也并不仅仅满足于让Swift困守iOS开发领域,加上早就公布了年底要开源,大家也很期待它作为一门通用编程语言在其他领域的作为。从各方面来看,Swift2.0增加了对异常处理的支持都在情理之中。从此你的App就不能轻易的狗带了~


ha~.jpg

我对异常处理的理解很浅薄,说实话平常自己也不怎么喜欢用。在我看来异常处理最重要的用途有两点:

  • 写底层框架的时候可以抛出一些异常让框架的使用者去处理,这样框架会显得更加灵活。

  • 保存错误日志,便于查询和调试。

像我上面那个函数,如果纯粹是自己用的话,其实我会选择在出错的地方直接处理错误或者打印错误信息,譬如把throw Error.InvalidURL改成

printLog("InvalidURL")return

这样也省得调用函数的时候一堆try-catch。当然有些错误当前函数确实是处理不了,那该抛还得抛。

上面那个函数还可以封装一下,分成两个,一个用来发送GET请求接收JSON数据,一个用来POSTJSON数据并接收返回信息。具体如下:

funcgetJsonFrom(url:String,completion:(json:JSON)->Void){do{trygetDataFrom(url,method:HTTPMethod.GET,parameter:nil){datain
letjson=JSON(data:data)//主线程进行UI操作
dispatch_sync(dispatch_get_main_queue()){
completion(json:json)
}
}
}catchError.InvalidURL{
printLog("GET:invalidurl")
}catch{
printLog("Unknownerror")
}

}

funcpostJson(dict:[String:String],toUrlurl:String,method:HTTPMethod.POST,parameter:dict){datain
letjson=JSON(data:data)//主线程进行UI操作
dispatch_sync(dispatch_get_main_queue()){
completion(json:json)
}
}
}catchError.InvalidURL{
printLog("POST:invalidurl")
}catchError.NoParameter{
printLog("Parameterisempty")
}catch{
printLog("Unknownerror")
}

}

完整代码在这里,里面还有一个图片缓存的函数,有兴趣的话可以看看。如果跟我有同样需求的同学可以把HttpManager.swiftclone下来直接拖到项目里,建议配合SwiftyJSON(一个很好用的第三方JSON解析库)使用,直接把Source文件夹里的SwiftyJSON.swift这个文件也一起拖到项目中好了,要用Cocoapods导入framework的话似乎只能支持iOS8之后的系统了。

对了还有一点,我一开始用JSON(data: data)来初始化JSON数据的时候总是不成功,于是我看了下SwiftyJSON中JSON这个struct的构造函数,它先调用了苹果提供的class func JSONObjectWithData(_ data: NSData,options opt: NSJSONReadingOptions) throws -> AnyObject函数,然后把返回的AnyObject对象赋值给自身属性object

publicinit(data:NSData,optionsopt:NSJSONReadingOptions=.AllowFragments,error:NSErrorPointer=nil){do{letobject:AnyObject=tryNSJSONSerialization.JSONObjectWithData(data,options:opt)
self.init(object)
}catchletaErrorasNSError{iferror!=nil{
error.memory=aError
}
self.init(NSNull())
}
}publicinit(_object:AnyObject){
self.object=object}

opt这个参数有三个可选值:MutableContainers,MutableLeaves,AllowFragments,分别表示:

  • 可以把数组或者字典转化成可变对象;

  • 可以把JSON对象树中作为叶子节点的字符串转化成可变字符串;

  • 允许解析最外层对象不是NSArrayNSDictionary实例的JSON数据

三种我都试了,都不行,最后我试了下[],也就是传入一个空值,居然行了。于是我索性把JSON的初始化函数改了:

publicinit(data:NSData,optionsopt:NSJSONReadingOptions=[],error:NSErrorPointer=nil){//其余不变

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...