阅读更多

0顶
0踩

移动开发
在iOS开发中进行网络请求时,一般是获取到服务器返回的data后,再根据需求转换成JSON,图像等信息。在Swift时代,如何使用泛型和extension来让数据解析工作更加优雅?且看本文详解。
一、过去这么干

我们在iOS开发中进行网络请求的时候,一般是获取到服务器返回的data后,再根据我们的需要转换成JSON,图像等信息:
 let myURL = NSURL(string: "http://imgs.xkcd.com/comics/scrabble.png")!
        let task = NSURLSession.sharedSession().dataTaskWithURL(myURL, completionHandler: { (data, response, error) -> Void in
            let image = UIImage(data: data)
            //use the image
        })

但如果你的应用中存在各种类型的返回数据,那么你可能就要在各个网络请求的中进行重复的处理了。

二、在Swift-beta时代

下面,我们使用swift中的泛型和extension让你的数据解析工作更优雅。

首先我们建立一个protocol:
public protocol ResponseConvertible{
    class func convertFromData(data:NSData!) -> (Self?,NSError?)
}

这个protocol负责把网络请求返回的NSData转化成我们想要的任何类型。 相信大家应该注意到了返回中的Self了,把返回定义为Self是因为这个接口本身是没有包含类型信息的,我们并不知道哪个类会实现这个接口,所以我们使用Self来指代将要实现这个接口的类。 接着,我们使用extension来为JSON(我使用的是SwiftJSON),UIImage,NSData这三个类实现我们的ResponseConvertible接口:
extension JSON:ResponseConvertible{
    public static func convertFromData(data:NSData!) -> (JSON?, NSError?){
        let value = JSON(data: data, options: NSJSONReadingOptions.MutableContainers, error: nil)
        switch value.type{
        case .Null:
            return (value, value.error)
        default:
            return (value, nil)
        }
    }
}
extension NSData:ResponseConvertible{
    public class func convertFromData(data: NSData!) -> (NSData?, NSError?) {
        return (data,nil)
    }
}
extension UIImage:ResponseConvertible{
    public typealias Result = UIImage
    public class func convertFromData(data: NSData!) -> (UIImage?, NSError?) {
        return (UIImage(data: data),nil)
    }
}

然后,我们再新建一个名为MyRequest的自定义的网络请求类:
class MyRequest <  T:ResponseConvertible> {  
    var url:NSURL  
    init(url:NSURL) {  
        self.url = url  
    }  
    //这里用一个简单的请求进行说明,实际应用中可以构建一个最适合你的网络请求框架  
    func aSimpleRequest(completionHandler:(T?,NSError!) -> ()){  
        let session = NSURLSession.sharedSession()  
        let task = session.dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in  
            if error == nil{  
                //用ResponseConvertible接口进行数据转换  
                let(object, converError) = T.convertFromData(data)  
                completionHandler(object,converError)  
            }  
        })  
        task.resume()  
    }  
}  

好了,准备工作完成,我们终于可以使用优化后的请求方法了。请求时,< T:ResponseConvertible>接受一个实现了ResponseConvertible接口的类型,例如UIImage:
let myURL = NSURL(string: "http://imgs.xkcd.com/comics/scrabble.png")!
        MyRequest<  UIImage>(url: myURL).aSimpleRequest({image,error in
            self.imageView.image = image
        })

三、现在应该这么干

不过,如果你现在把以上代码拷贝进你运行在Xcode6正式版的项目,你会发现Xcode会报错:



错误详情:
引用
Protocol 'ResponseConvertible' requirement 'convertFromData' cannot be satisfied by a non-final class ('NSData') because it uses 'Self' in a non-parameter, non-result type position

而这些代码在Swift-beta时代是能正常运行的。看来苹果在Swift1.0中对Self的用法进行了修改。

根据错误的提示,我们需要把使用了Self的类定义为final,而这在自定义的类中的确有用:
final class MyClass: {
    //...
}

但是对于UIImage,NSData这些系统的类就无能为力了。这个问题困扰了我好一会,stackoverflow无果,请教一些盆友都表示对Self的用法不熟或压根没动过Swift。

最后,还是在typealias的帮助下绕过了,typealias 可以为已经存在的类型和方法重新定义一个快捷名字,比如:
typealias Result = UIImage

这里的Result就相当于UIImage类型了。 引入typealias后,以上的代码做如下修改,就能在新版本的Xcode下运行了:
public protocol ResponseConvertible{
    typealias Result
    class func convertFromData(data:NSData!) -> (Result?,NSError?)
}

extension JSON:ResponseConvertible{
    public typealias Result = JSON
    public static func convertFromData(data:NSData!) -> (Result?, NSError?){
        let value = JSON(data: data, options: NSJSONReadingOptions.MutableContainers, error: nil)
        switch value.type{
        case .Null:
            return (value, value.error)
        default:
            return (value, nil)
        }
    }
}
extension NSData:ResponseConvertible{
    public typealias Result = NSData
    public class func convertFromData(data: NSData!) -> (NSData?, NSError?) {
        return (data,nil)
    }
}
extension UIImage:ResponseConvertible{
    public typealias Result = UIImage
    public class func convertFromData(data: NSData!) -> (UIImage?, NSError?) {
        return (UIImage(data: data),nil)
    }
}

class MyRequest< T:ResponseConvertible> {
    //这里用一个简单的请求说明,实际应用中可以构建一个最适合你的网络请求框架
    var url:NSURL
    init(url:NSURL) {
        self.url = url
    }
    func aSimpleRequest(completionHandler:(T.Result?,NSError!) -> ()){
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
            if error == nil{
                let(object, converError) = T.convertFromData(data)
                completionHandler(object,converError)
            }
        })
        task.resume()
    }
}

使用:
let myURL = NSURL(string: "http://imgs.xkcd.com/comics/scrabble.png")!
        MyRequest<  UIImage>(url: myURL).aSimpleRequest({image,error in
            self.imageView.image = image
        })

本文转载自:简书
  • 大小: 15 KB
来自: 简书
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • JavaScript事件类型中UI事件详解

    滚轮事件,使用鼠标滚轮或类似设备; 文本事件,当用户在文档中输入文本; 键盘事件,通过键盘在页面上执行操作; 合成事件,当为IME(Input Method Editor,输入法编辑器)输入字符时除法; 变动事件(mutation),...

  • 鼠标滚轮事件及解决滚轮事件多次触发问题

    1. 滚轮事件的兼容写法;2. 详解滚轮事件参考链接;3. 滚轮事件滚动过快,事件触发两次的两种解决方法

  • Javascript高级编程学习笔记(63)—— 事件(7)鼠标及滚轮事件

    Javascript高级编程学习笔记(63)—— 事件(7)鼠标及滚轮事件 鼠标与滚轮事件 鼠标事件是web开发中最常用的一类事件,毕竟鼠标是最主要的定位设备 DOM3级事件中定义了9个鼠标事件: click...

  • 13.4.3 鼠标与滚轮事件【JavaScript高级程序设计第三版】

    鼠标事件是Web 开发中最常用的一类事件,毕竟鼠标还是最主要的定位设备。DOM3 级事件中定义了9 个鼠标事件,简介如下。 click:在用户单击主鼠标按钮(一般是左边的按钮)或者按下回车键时触发。这一点对确保易访问...

  • JS鼠标与滚轮事件

    鼠标事件是 Web 开发中最常用的一类事件,毕竟鼠标还是最主要的定位设备。DOM3 级事件中定义了 9 个鼠标事件. click :在用户单击主鼠标按钮(一般是左边的按钮)或者按下回车键时触发。这一点对确保易访问性很重要...

  • JavaScript事件

    JavaScript事件

  • Javascript 事件详解

    一:事件流  事件流描述的是从页面中接收事件的顺序,IE和Netscape提出来差不多完全相反的事件流的概念,IE事件流是事件冒泡流,Netscape事件流是事件捕获流。 事件冒泡  IE的事件流叫做事件冒泡,即事件...

  • javaScript事件解析

    javaScript事件解析 事件流–事件冒泡和事件捕获 事件流就是描述页面接受事件的顺序。 冒泡结构上(非视觉上)嵌套关系的元素会存在冒泡事件功能,及同一事件,子元素向父元素冒泡。 捕获 IE没有 将...

  • JavaScriptAPI编程_事件

    网页中每个元素都可以产生某些可以触发JavaScript的事件,例如,我们可以在用户点击某个按钮时产生一个事件,然后去执行某些操作事件是由三部分组成,事件源,事件类型,事件处理程序.我们也称为事件三要素示例 注册事件/...

  • 《JavaScript 闯关记》之事件

    JavaScript 程序采用了异步事件驱动编程模型。在这种程序设计风格下,当文档、浏览器、元素或与之相关的对象发生某些有趣的事情时,Web 浏览器就会产生事件(event)。例如,当 Web 浏览器加载完文档、用户把鼠标...

  • JavaScript事件类型

    1 UI事件 UI事件指的是那些不一定与用户操作有关的事件。...第一种方式是使用如下所示的 JavaScript代码: EventUtil.addHandler(window, “load”, function(event){ alert(“Loaded!”); }); 第二种指定 onload

  • javascript高级程序设计读书笔记——事件总结

    第13章 事件 1.1 事件冒泡  事件开始的时候从最具体的元素接收,然后逐级向上传播到较为不...由于老版本的浏览器不支持事件捕获,因此更加建议使用事件冒泡,有特殊需要的时候在使用事件捕获。 1.3 DOM事件流  D

  • JavaScript 中常用事件有哪些?

    事件是可以被 JavaScript 侦测到的行为。网页中的每个元素都可以产生某些可以触发JavaScript函数的事件。比方说,我们可以在用户点击某按钮时产生一个 onClick 事件来触发某个函数。事件在HTML页面中定义。

  • 【JavaScript 事件】站在巨人身上俯看_js事件(详细版)

    js事件(详细笔记)

  • DOM事件机制

    HTML DOM 允许 JavaScript 对 HTML 事件...JavaScript 能够在事件发生时执行,比如当用户点击某个 HTML 元素时。JavaScript与HTML之间的交互是通过事件实现的。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。

  • 游戏操作按键识别的原理-----JavaScript鼠标键盘事件

    可能有人或许会好奇为什么玩游戏中敲击某个键或者鼠标左键/滚轮/右键敲击就能执行游戏中所设定的操作,难道是游戏开发者不用写程序计算机就能自动识别你敲击的是哪个键并执行,NO! NO! NO! 这个与鼠标键盘事件相关。

  • JavaScript DOM事件流事件捕获事件冒泡

    我们可以使用侦听器(或事件处理程序)来预订事件,以便事件发生时执行相应的代码。说白了,就是当我们对页面上的某些元素进行某些操作(比如鼠标单击)时产生一些特定的行为。比如鼠标单击一个按钮然后弹出一个...

  • JavaScript 事件学习笔记

    事件 事件流——事件冒泡流、事件...DOM2 Event规范规定事件流分三阶段:事件捕获、到达目标、事件冒泡 通常不认为到达目标后的事件处理阶段不属于事件捕获,而被认为是冒泡阶段的一部分 现代浏览器会在捕获阶段在事件

  • spring-ai-spring-boot-autoconfigure-1.0.0-M5.jar中文文档.zip

    # 【spring-ai-spring-boot-autoconfigure-***.jar中文文档.zip】 中包含: 中文文档:【spring-ai-spring-boot-autoconfigure-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【spring-ai-spring-boot-autoconfigure-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【spring-ai-spring-boot-autoconfigure-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【spring-ai-spring-boot-autoconfigure-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【spring-ai-spring-boot-autoconfigure-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: spring-ai-spring-boot-autoconfigure-***.jar中文文档.zip,java,spring-ai-spring-boot-autoconfigure-***.jar,org.springframework.ai,spring-ai-spring-boot-autoconfigure,***,org.springframework.ai.autoconfigure.anthropic,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,springframework,spring,ai,boot,autoconfigure,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【spring-ai-spring-boot-autoconfigure-***.jar中文文档.zip】,再解压其中的 【spring-ai-spring-boot-autoconfigure-***-javadoc-API文档-中文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-spring-boot-autoconfigure</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'org.springframework.ai', name: 'spring-ai-spring-boot-autoconfigure', version: '***' Gradle (Short): implementation 'org.springframework.ai:spring-ai-spring-boot-autoconfigure:***' Gradle (Kotlin): implementation("org.springframework.ai:spring-ai-spring-boot-autoconfigure:***") ``` # 含有的 Java package(包): ``` org.springframework.ai.autoconfigure.anthropic org.springframework.ai.autoconfigure.azure.openai org.springframework.ai.autoconfigure.bedrock org.springframework.ai.autoconfigure.bedrock.anthropic org.springframework.ai.autoconfigure.bedrock.anthropic3

  • 50页-道路环卫保洁服务项目管理计划方案.pdf

    在当今智慧城市的建设浪潮中,智慧环卫作为城市管理的重要组成部分,正以其独特的魅力引领着环卫行业的变革。本方案旨在通过一系列高科技手段,如物联网、大数据、云计算等,全面提升环卫作业效率与管理水平,为城市居民创造更加清洁、宜居的生活环境。 一、智慧环卫系统概述与核心亮点 智慧环卫系统是一个集机械化保洁、垃圾清运、设施管理、事件指挥调度等多功能于一体的综合性管理平台。其核心亮点在于通过高精度定位、实时监控与智能分析,实现环卫作业的精细化管理。例如,机械化保洁管理子系统能够实时监控机扫车、洒水车等作业车辆的运行状态,自动规划最优作业路线,并根据作业完成情况生成考核评价报表,极大地提高了作业效率与服务质量。同时,垃圾清运管理子系统则通过安装GPS定位设备和油量传感器,对清运车辆进行全方位监控,确保垃圾清运过程的规范与高效,有效解决了城市垃圾堆积与随意倾倒的问题。此外,系统还配备了垃圾箱满溢报警系统,通过智能感应技术,当垃圾箱内垃圾达到预设高度时自动报警,提醒作业人员及时清运,避免了因垃圾满溢而引发的居民投诉与环境污染。 二、智慧环卫系统的趣味性与知识性融合 智慧环卫系统不仅实用性强,还蕴含着丰富的趣味性与知识性。以餐厨垃圾收运管理子系统为例,该系统通过为餐厨垃圾收运车辆安装GPS定位、车载称重、视频监控等多种感知设备,实现了对餐厨垃圾收运过程的全程监控与智能管理。作业人员可以通过手机APP实时查看车辆位置、行驶轨迹及收运情况,仿佛在玩一场现实版的“垃圾追踪游戏”。同时,系统还能自动生成餐厨垃圾收运统计报表,帮助管理人员轻松掌握收运量、违规情况等关键数据,让数据管理变得既科学又有趣。此外,中转站视频监控子系统更是将趣味性与实用性完美结合,通过高清摄像头与双向语音对讲功能,实现了对中转站内外环境的实时监控与远程指挥,让管理人员足不出户就能掌控全局,仿佛拥有了一双“千里眼”和一对“顺风耳”。 三、智慧环卫系统的未来展望与社会价值 随着科技的不断进步与智慧城市建设的深入推进,智慧环卫系统将迎来更加广阔的发展前景。未来,智慧环卫系统将更加注重数据的深度挖掘与分析,通过大数据与人工智能技术,为城市环卫管理提供更加精准、高效的决策支持。同时,系统还将加强与其他城市管理系统的互联互通,实现资源共享与协同作战,共同推动城市管理的智能化、精细化水平。从社会价值来看,智慧环卫系统的推广与应用将有效提升城市环境卫生质量,改善居民生活环境,提升城市形象与竞争力。此外,系统还能通过优化作业流程、减少资源浪费等方式,为城市可持续发展贡献重要力量。可以说,智慧环卫系统不仅是城市管理的得力助手,更是推动社会进步与文明发展的重要力量。

Global site tag (gtag.js) - Google Analytics