swift的闭包和c,oc中block是差不多的,其实swift中的全局和嵌套函数实际上也是一种特殊的闭包,闭包有三种形式:

(1)全局函数是有一个名字,但不能捕获任何值的闭包

(2)嵌套函数是有一个名字,可以捕获在函数内的值得闭包

(3)闭包表达式是一个轻量级的语法,可以从上下文中捕获值

闭包表达是一个干净,清晰,鼓励简介,优化的语法,优化包括:

(1)从上下文中推断参数和返回类型

(2)简单的闭包表达可以省略return

(3)简写参数名

(4)尾部闭包语法

(一)闭包表达

闭包表达就是以一个简明准确的方式写一个内联包

(二)sort函数

swift标准库提供了sort函数,用来排序已知类型的数组,通过你提供的排序包规则输出

        let originalNames = ["Chris","Alex","Ewa","Barry","Daniella"]
        var currentNames = originalNames.sort(backwards)
    func backwards(s1: String,s2: String) -> Bool {
        return s1 > s2
    }
这么表达有点囧长啊(long-winded),但是在这这个栗子也算比较好和合适的

下面用闭包表达一下

        var reverse = originalNames.sort({ (s1: String,s2: String) -> Bool in
            
            return s1 > s2
            
        })
解释:(1)in前面的是参数类型和返回值类型

(2)in后面是实现部分

(3)整个表达式用{}号括起来

由于swift有推断类型功能,闭包可以从上下文推断类型,所以上面的表达式还可以写成:

        var reverse = originalNames.sort({s1,s2 in return s1 > s2})
        print(reverse)
另外,单行表达式可以忽略return关键字,所以上面的表达式又可以写成:
        var reverse = originalNames.sort({s1,s2 in s1 > s2})
        print(reverse)
通过sort函数和sort的第二个参数我们就可知道这个函数一定是返回一个bool类型,返回值只有一个单一的表达式,所以return可以省略,并且不会造成歧义

(三)简写参数名

swift对于内联包自动提供了参数名的简写,这些简写名用来关联参数,那么这些看不到简写名是怎么简写的呢?就是$0,$1,$2....

如果你写闭包表达用了简写名,那你写的所有参数就可以省了,因为人家已经相当于给你提供了参数,只是简写了,就不用你写了,写了都TM浪费感情啊,不光浪费自己的,还浪费swift的,尤其是人家程序员的,我都把闭包简成这样了,你就不要写那么麻烦添乱了,省的大家都心里堵得慌,废话不多说了,下面检测一下这个简写:

        var reverse = originalNames.sort( { $0 > $1 } )
        print(reverse)

0,1这个就是从第一个参数开始关联,大家都是干程序的,知道程序排序都是从0开始吧,这个你在问为什么,我就只能呵呵了

(四)操作符(有的也叫运算符)函数

由于swift的String类型有规定两个字符的比较,并且返回的是Bool类型,所以上面我们可以写的再简单点,直接传一个操作符(运算符),swift就会自己推断调用string自身规定的实现

         var reverse = originalNames.sort(>)

(五)Trailing(尾部)闭包

意思就是把闭包实现放在尾部来写,为什么要放在尾部呢,因为闭包实现太长了,可能会影响代码的可读性,美观性,所以就放在最后面实现好了

swift数组有一个map(映射)方法,仅仅是采用闭包表达作为参数像里面传递的。这个闭包会遍历数组的每个元素,并且返回相应的可选类型的映射。映射的核心和返回值的类型都是又闭包规定的。当使用map方法后,会返回一个新的数组, 这个数组包含了所有新的映射的值,下面举一个例子(把Int型数组转换成Strin型的数组)说明一下:

        let digitNames = [0:"Zero",1:"One",2:"Two",3:"Three",4:"Four",5:"Five",6:"Six",7:"Seven",8:"Eight",9:"Nine"]
        let numbers = [16,58,510]
        let strings = numbers.map() {
            (var number) -> String in
            var output = ""
            while number > 0 {
                output = digitNames[number % 10]! + output
                number /= 10
            }
            return output
        }
        
        print(strings)
解释:首先声明一个字典,在声明一个数组,调用map方法,自己写实现

其次,通过return,swift已经推断strings是一个字符串型的数组了

最后,就看打印结果了

如果闭包是函数的唯一参数,函数后面的括号可以省略,所以上面的函数还可以这么写:

        let strings2 = numbers.map {
            (var number) -> String in
            var output = ""
            while number > 0 {
                output = digitNames[number % 10]! + output
                number /= 10
            }
            return output
        }
        
        print(strings2)

在这里,number前面使用var修饰的,这个在函数有讲,就是在内部调用可变,相当于在函数内部声明了一个变量,并把number(数组的元素)传递给了这个变量,函数调用结束,他也就释放了

规定的返回类型是String类型,存储在返回的数组中了

注意:上面字典后面跟了一个感叹号,因为字典下标语法总是返回一个可选值的如果查询失败的话,但是在上面的例子中,一定要确保字典下标值是有效地,因此我们要强制拆包,得到存储在可选返回值的中的String类型值

(六)值捕获

说白了,就是闭包可以从上下文中捕获值,用为己用(变量常量都可以,还可以自己改变其值),下面举一个简单的函数嵌套的例子

        let incrementByTen = makeIncrementer(forIncrement: 10)
        print(incrementByTen())
    }

    func makeIncrementer(forIncrement amout: Int) -> Void -> Int {
        
        var runningTotal = 0
        
        func increment() -> Int {
            runningTotal += amout
            return runningTotal
        }
        
        return increment
    
    }
func increment()这个函数就捕获到了runningTotal和amout的值,makeIncrementer这个函数返回的是一个函数类型(一个不接收参数且返回值类型为Int类型的函数)
        let incrementByTen = makeIncrementer(forIncrement: 10)
        incrementByTen()
        incrementByTen()
        print(incrementByTen())
上面的打印结果猜一下是多少?这是因为闭包自动帮我们存储了变量的值,调动同一函数会自动加,如果我们再定义一个函数呢?比如下面两个的输出结果
        let incrementBySeven = makeIncrementer(forIncrement: 7)
        incrementByTen()
        print(incrementByTen())
        print(incrementBySeven())
由上面得知我们再定义一个函数闭包会引用一个新值给这个新的函数,和前面的函数不会混淆,而原始的还是执行自己的功能

注意:如果我们把一个闭包定义成了类实例的属性,通过引用这个实例或者它的成员,会产生一个强引用,不过给了我们解决办法,这个我会在后面学习之后进行讲解,谢谢

(七)闭包是引用类型

在上面的例子中,incrementByTen和incrementBySeven是常量,但是他们引用的闭包仍然可以改变runningTotal的值,这是因为函数和闭包都是引用类型的,当我们把函数或者闭包赋给一个常量或者变量时,实际上是我们用这个常量或者变量引用那个闭包,打印里面调用了也算也用,在打印下面的代码中runningTotal的值已经被+10了,

        let alsoIncrementByTen = incrementByTen
这里面的alsoIncrementByTen是incrementByTen+10的结果,不信可以自己尝试下

好啦,闭包也讲完了,下次我会介绍swift中的枚举

swift学习之闭包closure的更多相关文章

  1. html5使用canvas实现弹幕功能示例

    这篇文章主要介绍了html5使用canvas实现弹幕功能示例的相关资料,需要的朋友可以参考下

  2. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. 前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)

    这篇文章主要介绍了前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. H5 canvas实现贪吃蛇小游戏

    本篇文章主要介绍了H5 canvas实现贪吃蛇小游戏,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

  6. ios – 声明NSDictionary并在Swift中添加键值对?

    我一直在尝试使用类类型键和值来声明一个NSDictionary,如下所示:这里,“Category”和“SubCategory”是全局类.我知道我不能将类类型用于关键字段.但是,无论如何,我应该做到这一点.有没有办法做到这一点?如何声明专门的NSDictionary或类似的东西来做到这一点?

  7. ios – parse.com用于键,预期字符串的无效类型,但是得到了数组

    我尝试将我的数据保存到parse.com.我已经预先在parse.com上创建了一个名为’SomeClass’的类.它有一个名为’mySpecialColumn’的列,其数据类型为String.这是我尝试使用以下代码保存数据的代码:如果我运行这个我得到:错误:密钥mySpecialColumn的无效类型,预期字符串,但得到数组这就是我在parse.com上的核心外观:有谁知道我为什么会收到这个错误?

  8. ios – 在Swift中将输入字段字符串转换为Int

    所以我非常擅长制作APP广告Swift,我试图在文本字段中做一些非常简单的输入,取值,然后将它们用作Int进行某些计算.但是’vardistance’有些东西不正确它是导致错误的最后一行代码.它说致命错误:无法解开Optional.None解决方法在你的例子中,距离是一个Int?否则称为可选的Int..toInt()返回Int?因为从String到Int的转换可能失败.请参阅以下示例:

  9. ios – Swift相当于`[NSDictionary initWithObjects:forKeys:]`

    Swift的原生字典是否与[NSDictionaryinitWithObjects:forKeys:]相当?假设我有两个带键和值的数组,并希望将它们放在字典中.在Objective-C中,我这样做:当然我可以通过两个数组迭代一个计数器,使用vardict:[String:Int]并逐步添加东西.但这似乎不是一个好的解决方案.使用zip和enumerate可能是同时迭代两者的更好方法.然而,这种方法

  10. 如何在iOS中检测文本(字符串)语言?

    例如,给定以下字符串:我想检测每个声明的字符串中使用的语言.让我们假设已实现函数的签名是:如果没有检测到语言,则返回可选字符串.因此,适当的结果将是:有一个简单的方法来实现它吗?

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部