『iOS语法』闭包语法与实战

2018-09-23  本文已影响23人  mymdeep

『iOS语法』闭包语法与实战

闭包这种语法,其实很多语言都在用,学过Android的朋友,一定发现,在gradle中用的很多。
iOS的闭包有一些自己语言的特性,这里一点点介绍一下。

写法

{(parameters) -> return type in
   statements
}

闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。
所有内容都写在{}中。

示例

 var myClosure: () -> String = {
         () ->  String in
        return "a"
    }

这是定义了一个没有入参,返回值为String的闭包,然后将这个闭包赋值给myClosure,myClosure的类型为() -> String
这么解说就有点一目了然了吧。
这种没有入参的闭包还可以简写为:

var myClosure: () -> String = {
        return "a"
    }

那如果有参数的闭包呢?

 var myClosure1: (String,String) -> Int = {
     (val1: String, val2: String) -> Int in
        return val1.count+val2.count
    }

使用

对于有返回值的闭包,可以用来对某些变量赋值如:

var count1:Int = myClosure1("aa","bbb")

myClosure1已经之前声明了。
如果没有生命也可以这样使用:

 var count2:Int = {
            (val1: String, val2: String) -> Int in
            return val1.count+val2.count
        }("aa","bbb")

这样看着是不是有些别扭?为什么中括号后面还有跟一个()
如果觉得不好理解,可以这样想:

 {
            (val1: String, val2: String) -> Int in
            return val1.count+val2.count
        }

这个和myClosure1是可以互相替换的,myClosure1调用的时候为什么加(),这么说我想大家就容易明白了。
这种形式的闭包还可以简写为:

 var count2:Int = {
            return $0.count+$1.count
        }("aa","bbb")

其中0就表示第一个参数1表示第二个参数,以此类推。感觉是不是特别方便。

应用

在实际的开发过程中,其实很多地方都在用闭包,这里随便举几个例子。

回调

当需要使用异步回调的时候,可以传入一个闭包,如:

func test(callback: (String) ->Void)  {
  //do somethings
    callback("result")
}

这个callback就是传入的回调闭包,我们可以在调用的时候传入:

test { (result) in
            print(result)
        }

其实还有一种写法,就是函数返回一个闭包的类型:

func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}

但是个人决定这种写法让程序的可读性变的很差,尽量避免这种写法。

数组方法

在数组中可以使用闭包完成很多事情(这里只是举个例子,除了数组,字典类型,同样提供了很多闭包入参的方法)

map

Map是数组的一个方法,他将传入的闭包的返回值生成一个数组:

let array = ["aaa","bbb","ccc","ddd","eee","fff"]
let array1 = array.map { (str) -> Bool in
            return str.contains("aa")
        }
let array2 = array.map {
            return $0.contains("aa")
        }
let array3 = array.map {
             $0.contains("aa")
        }

结果如下:
map 返回 [true, false, false, false, false, false]

filter

Filter虽然传入的闭包也是布尔的返回值,实际是利用这个返回值做一个筛选,也就是满足条件的(True)生成一个新的数组,如:

  let array7 = array.filter { (str) -> Bool in
            return str.count>=3
        }
let array8 = array.filter {
            $0.count >= 3
        }

这两种写法效果是一样的。由于数组中所有的元素都满足这个条件,所以最终结果是:
map 返回 ["aaa", "bbb", "ccc", "ddd", "eee", "fff"]
我们可以再是一种方式:

  let array9 = array.filter {
             $0.contains("aa")
        }

这个闭包跟上面例子中map传入的闭包一样,但是最终返回可是不一样的,map返回的是一个布尔数组,filter返回的是一个满足条件的数组:
map 返回 ["aaa"]

reduce

Reduce这个方法比较特殊,他的参数有两个,第一个为初始值,第二个为闭包,这个闭包的定义中有两个参数,一个就是初始值,一个就是遍历数组中的元素。最终返回的值,就是一个确定的值,而不再是一个数组,举个例子吧,我们需要遍历数组,统计数组中所有字符串长度的和。

 let count11 = array.reduce(0) { (count, str) -> Int in
            return count + str.count
        }
let count22 = array.reduce(0) {
             $0 + $1.count
        }

上面两种写法效果是一样的。这里需要注意一个问题,如果一个方法有两个参数,最后一个是闭包,可以将闭包前面的参数写在括号中,如(0),闭包跟在最后

reduce(第一个参数) {
             闭包
        }

接着说上面的例子。
0表示初始化为0,也就是count的初始值为0,然后count每次都加元素的长度,遍历一遍,也就是最后总的长度了。

今天关于闭包就介绍这么多。闭包利用好可以使代码写起来更简单,但是也不能滥用,导致可读性变差。

上一篇 下一篇

猜你喜欢

热点阅读