谈谈Swift的extension

3.times { puts 'hello world' } 这是一条Ruby语句,它会打印“hello world”三次,意图清晰,语法简洁。

如果你是C或者Java等语言的使用者,而从未接触过Ruby,此时是不是有种打开了新世界的大门的感觉_。反正当初我刚接触Ruby那会儿时常会感叹,啊原来代码还可以这么写。。。Ruby的灵活与优雅当然远不仅于此,这里就不展开了。今天的重点是,Swift也可以这么写。

首先我们要明确,Ruby之所以可以这么写是因为它是一个纯面向对象的语言,在Ruby的世界中,一切皆对象,所有的事物都有一个共同的祖先——Object3的类型是Fixnum,当然也是一个对象,所以它有自己的方法。times就是一个方法,可以看出应该是接收一个代码块(本例中为{puts 'hello world'}),然后调用它self(本例中self即为3)次。

而在Swift中,Int是一个struct(结构体),并不是个class。但是Swift中的struct与别的语言中的struct不同的是,struct内部也可以定义方法。所以条件满足了,现在就差个times方法了。

嗯,很遗憾Swift的Int并没有times方法。不过没关系,这个时候extension就派上用场了。没有我们就自己写一个嘛,私人化定制,满足一切突如其来的需求。先上代码好了: 定义:

extension Int {
    func times(closure: () -> ()) {
       for _ in 1...self {
            closure()
        }
    }
}

调用: 3.times { println("hello world") }

是不是跟开头Ruby语句有异曲同工之妙?extension不仅可以扩展方法,还可以扩展计算属性。比如《The Swift Programming Language》中的一个例子:

extension​ ​Double​ {
​    ​var​ ​km​: ​Double​ { ​return​ ​self​ * ​1_000.0​ }
​    ​var​ ​m​: ​Double​ { ​return​ ​self​ }
​    ​var​ ​cm​: ​Double​ { ​return​ ​self​ / ​100.0​ }
​    ​var​ ​mm​: ​Double​ { ​return​ ​self​ / ​1_000.0​ }
​    ​var​ ​ft​: ​Double​ { ​return​ ​self​ / ​3.28084​ }
​}
​let​ ​oneInch​ = ​25.4​.​mm
​println​(​"One inch is ​\(​oneInch​)​ meters"​)
​// prints "One inch is 0.0254 meters"
​let​ ​threeFeet​ = ​3​.​ft
​println​(​"Three feet is ​\(​threeFeet​)​ meters"​)
​// prints "Three feet is 0.914399970739201 meters”

extension在实际的开发中可以有很多应用,使用得当能显著提高代码的可读性,平常我们自己写的大多数辅助类其实都可以转化为extension。譬如我最近在自己的项目中给被点击的UIView(比如button)写了一个小动画,点击了之后组件会上浮一下,并且同时会有一下阴影效果。 定义:

extension UIView {
    func animateWhenClicked() {
        self.backgroundColor = UIColor(white: 0.9, alpha: 0.5)
        self.layer.transform = CATransform3DMakeScale(1, 1, 0)
        UIView.animateWithDuration(0.9, animations: {
            self.backgroundColor = UIColor.whiteColor()
            self.layer.transform = CATransform3DMakeTranslation(1, 1, 1)
        })
    }
}

使用(仅点击动画部分代码):

button.addTarget(viewCtrl, action: "clicked:", forControlEvents: .TouchUpInside)
func clicked(sender: UIButton) {
    sender.superview!.animateWhenClicked()
}

iOS Simulator Screen Shot 2015年8月26日 下午11.39.45.png

大概就是右上角的效果,呃,静态图看不出来,各位要是有兴趣可以拿我的扩展方法然后自己初始化个Button去跑跑看(直接sender.animateWhenClicked()就好,不用superview)。因为我在项目中的Button是一个自定义的贪婪Button,只要点击Button的父视图就会响应点击事件,所以是Button的superview调用了animateWhenClicked,这也是我把这个动画扩展到UIView而不是UIButton的原因。

我个人很喜欢extension,平常也经常使用。extension也可用于后期项目维护,可以在不修改旧代码的前提下扩展旧代码的功能。而且对于NSObject的子类或者有dynamic标记的方法,利用扩展还可以在运行时对某些方法的实现进行替换,类似于OC的Swizzle,今天就不展开了,下次有空继续。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术点滴

抽象工厂模式(Abstract Factory)

抽象工厂模式(Abstract Factory) 抽象工厂模式(Abstract Factory)[Kit] 意图:提供一个创建一系列相关或相互依赖对象的接口,...

265100
来自专栏IMWeb前端团队

React高阶组件(译)

本文作者:IMWeb zzbozheng 原文出处:IMWeb社区 未经同意,禁止转载 原文:https://daveceddia.com/extra...

20460
来自专栏hightopo

HT for Web基于HTML5的图像操作(二)

17020
来自专栏狮乐园

async-for-js

插入3个div元素,其中第二个div元素使用setTimeout模拟异步操作,理想的插入顺序为div1 div2 div3,但这里的代码的插入顺序为div1 d...

14320
来自专栏HT

HT for Web基于HTML5的图像操作(二)

上篇介绍了HT for Web采用HTML5 Canvas的getImageData和setImageData函数,通过颜色乘积实现的染色效果,本文将再次介绍另...

29380
来自专栏Golang语言社区

如何理解 golang nil

golang 中的 nil 是不同于其他语言的,为了更好的理解 nil,在此我将尝试一步一步揭示 nil 在 golang 中的一些操作和现象。 1. nil ...

33850
来自专栏HTML5学堂

2016.05 第三周 群问题分享

HTML+CSS 一个div里面有个img标签,div的高度由img撑开;img的兄弟级有个div要使内层div的高度等于外层div的高度,除了用JS实现,还能...

373130
来自专栏前端儿

DOM中 property 和 attribute 详解

其实Attribute和Property这两个单词,翻译出来都是“属性”,《js高级程序设计》书中翻译为“特性”和“属性”,以示区别。从而我们也可以顾名思义

10620
来自专栏互联网杂技

h5新功能data-*,好好利用,还能做数据双向绑定

标题是data-,但是这里主要讲伪元素,看明白就知道了 1、jQuery Selectors 获取伪元素的属性值 虽然JS里没有可以直接操作伪元素的选择符,然而...

32840
来自专栏编程

Python读书笔记4

上期介绍了数字型数据,本期和大家分享的是另一个常见的数据类型字符串,可以简单的理解为Excel中的文本。 Excel在存储内核中其实只有两种:文本、数字;日期归...

24850

扫码关注云+社区

领取腾讯云代金券