Swift 入门技术 - 闭包
cf8ein2l8e
8年前
<p>swift 中的闭包类似于 OC 中的 Block,但是使用比 Block 更广泛</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/4d98fa82e02183ecb692e328be57193c.png"></p> <h3><strong>闭包的简单说明</strong></h3> <ol> <li>保存提前准备好的代码</li> <li>在需要的时候执行</li> <li>可以当做参数传递</li> <li>在 OC 中 Block 是匿名的函数</li> <li>在 Swift 中闭包是特殊的函数</li> </ol> <h3><strong>闭包的使用场景</strong></h3> <ol> <li>异步执行完成回调</li> <li>控制器间回调</li> <li>自定义视图回调</li> <li>回调的特点 <ul> <li>以参数回调处理结果</li> <li>返回值为 Void</li> </ul> </li> </ol> <h3><strong>闭包的简单使用</strong></h3> <ol> <li> <p>无参数无返回值</p> <pre> <code class="language-swift">//最简单的闭包(无返回值无参数) // ( ) -> ( ) let bibao1 = { print("hello, world") } //调用闭包 bibao1()</code></pre> </li> <li> <p>有参数无返回值</p> <ul> <li>在闭包中,参数、返回值、实现代码都可以写在 { } 中</li> <li>使用一个关键字 in 分割定义和实现</li> <li> <p>{ 形参列表 -> 返回值类型 in //实现代码 }</p> <pre> <code class="language-swift">//带参数无返回值的闭包 // ( Int ) -> ( ) let bibao2 = { (x: Int) -> () in print(x) } bibao2(10)</code></pre> </li> </ul> </li> <li> <p>有参数有返回值</p> <pre> <code class="language-swift">//带参数带返回值的闭包 // (Int) -> Int let bibao3 = { (x: Int) -> Int in return x + 10 } print(bibao3(10))</code></pre> </li> </ol> <h3><strong>闭包作为参数传递</strong></h3> <ul> <li> <p>闭包和 Block 一样可以作为参数进行传递</p> <pre> <code class="language-swift">//闭包作为参数传递 // (Int, Int) -> Int let bibao4 = { (x: Int, y: Int) -> Int in return x + y } func test(x: Int, y: Int, bibao: (Int, Int) -> Int) { bibao(x, y) } test(x: 10, y: 20, bibao: bibao4)</code></pre> </li> </ul> <h3><strong>尾随闭包</strong></h3> <ul> <li>如果函数的最后一个参数是闭包,函数参数可以提前结束,最后的一个参数使用 { } 来包装闭包的代码</li> <li> <p>使用尾随闭包对上述的参数传递代码进行调整,可以使用以下方式进行修改</p> <pre> <code class="language-swift">//尾随闭包 func test(x: Int, y: Int, bibao: (Int, Int) -> Int) { bibao(x, y) } test(x: 10, y: 20) { (x, y) -> Int in return x + y }</code></pre> </li> </ul> <h3><strong>逃逸闭包</strong></h3> <ul> <li>在 Swift 中 闭包默认是非逃逸的,不能被其他对象引用</li> <li> <p>@escaping 修饰的就是逃逸闭包,可以被其他对象引用</p> <pre> <code class="language-swift">func test(a: Int, aa: ()->()) { aa() } func getData(result: @escaping ([String]) -> ()) { test(a: 10, aa: { result(["1", "2"]) }) }</code></pre> </li> </ul> <h3><strong>闭包的循环引用</strong></h3> <ul> <li>由于 { } 的作用域,在使用闭包的同时要注意循环引用的问题</li> <li>在 OC 中可以使用 weak 和 unsafe_unretained 两种方式</li> <li> <p>在 Swift 中主要使用 weak 和 unowned 两种方式来解决</p> <ol> <li> <p>weak</p> <ul> <li>Swift 中推荐使用的方法</li> <li>需要注意解包问题</li> <li>修饰的 self 都是弱引用</li> </ul> <pre> <code class="language-swift">class Person { var num: Int = 0 var bb: (() -> ())? // weak 方式一 func test1() { weak var weakSelf = self bb = { print("test1", weakSelf!) let pr = weakSelf?.num pr! + 10 } bb!() } // weak 方式二 func test2() { bb = { //标识,在这个闭包里使用的所有 self 都是弱引用 [weak self] () -> () in print(self!) print(self!) } bb!() } }</code></pre> </li> <li> <p>unowned</p> <ul> <li>修饰的 self 都是 assign 的,不会强引用</li> <li>如果对象释放,指针地址不会变化</li> <li>若被释放之后继续调用,会出现野指针问题</li> </ul> <pre> <code class="language-swift">class Person { var num: Int = 0 var bb: (() -> ())? // unowned 方式一 func test1() { unowned let weakSelf = self bb = { print("test1", weakSelf) let pr = weakSelf.num pr + 10 } bb!() } // unowned 方式二 func test2() { bb = { //标识,在这个闭包里使用的所有 self 都是弱引用 [unowned self] () -> () in print(self) print(self) } bb!() } }</code></pre> </li> </ol> </li> </ul> <p> </p> <p>来自:http://www.jianshu.com/p/880e9e6d99d7</p> <p> </p>