闭包(特殊的函数)

简介: 闭包(特殊的函数)
  • 1.闭包的介绍


  • 闭包和OC中的block非常相似
  • OC中的block是匿名的函数
  • Swift中的闭包是一个特殊的函数
  • block和闭包都经常用于回调
  • 注意:闭包和block一样,第一次使用时可能不习惯它的语法,可以先按照使用简单的闭包,随着学习的深入,慢慢掌握其灵活的运用方法.


  • 2.闭包的使用


  • 1.先回顾一下block的使用


@property(nonatomic,strong) void(^myblock)();
// block 的格式: 返回值类型(^block名称) (参数列表)
self.myblock = ^(){
        NSLog(@"block的打印");
 };
self.myblock();
  • 2.闭包的基本介绍
    /*
    * 闭包和oc中的block非常相似
    * oc中的block类似于匿名函数
    * 闭包是用来定义函数
    * 作用: block 是用于保存一段代码,在需要的时候执行
    *      闭包也是用于保存一段代码,在需要的时候执行
    * 做一个耗时的操作
    */


/*
 * 闭包的基本格式:
   in的含义是用来区分形参返回值和要执行的代码
 *  {
      (形参列表) -> (返回值)
       in
       需要执行的代码
    }
 *
 */
  loadData {
    print("回调")
}
func loadData(request:()->()){
    print("执行耗时操作")
    request()
}
  • 3.闭包的几种格式
  • 1.将闭包通过实参传递给函数


loadData (request: { 
    print("回调")
 })
 func loadData(request:()->()){
    print("执行耗时操作")
    request()
 }
  • 2.如果闭包是函数的最后一个参数,那么闭包可以写在函数()的后面
    loadData() {


print("回调2")
 }
 func loadData(request:()->()){
     print("执行耗时操作")
     request()
 }
  • 3.如果函数只接受一个参数,并且这个参数是闭包,那么()可以省略
    loadData {


print("回调2")
}
func loadData(request:()->()){
     print("执行耗时操作")
     request()
}
  • 4.闭包的返回值和参数

/*
 *  两个闭包  创建一个 UIscrollview 上添加button
 *
 *
 */
let sc1 = createScrollview(buttonCount: { () -> Int in
    return 15
}) { (index) -> UIView in
    let width1 = 80
    let button = UIButton()
    button.backgroundColor = UIColor.red
    button.frame = CGRect(x:index*width1,y:10,width:width1,height:80)
    button.setTitle("标题\(index)", for: UIControlState(rawValue: 0))
    return button
    }
view.addSubview(sc1)
    /*
     * 要求定义一个方法来创建UIScrollView,
     * 1.并且上面有多个按钮,必须通过闭包来告诉该方法
     * 2.并且如何创建按钮也需要闭包来创建
     */
    // 5.将scrollview添加到控制器的view上
    // 特点: 没有写self
    // swift推荐:能不写self就不写self
    func createScrollview(buttonCount:()->Int,buttonIndex1: (_ num:Int)->UIView) -> UIScrollView {
    // 数组的数量
    let count = buttonCount()
    // 1.创建scrollview
    let sc = UIScrollView(frame: CGRect(x:0,y:64,width:414,height:100))
    sc.backgroundColor = UIColor.blue
    view.addSubview(sc)
    // 2.在scrollview上放置button
    for i in 0..<count {
        /*
        let button = UIButton()
        button.backgroundColor = UIColor.red
        button.frame = CGRect(x:i*width1,y:10,width:width1,height:80)
        button.setTitle("标题\(i)", for: UIControlState(rawValue: 0))
        sc.addSubview(button)
        */
        let button = buttonIndex1(i)
        sc.contentSize = CGSize(width:CGFloat(count) * button.bounds.width,height:100)
        sc.addSubview(button)
    }
    return sc
}
  • 5.循环引用


import UIKit
class ViewController: UIViewController {
 /*
  * 在swift中,如果在某个类中定义一个属性,那么这个属性必须要初始化,否则就会报错
  * 如果暂时不想初始化,那么可以在后面写上一个 ? 也就是可选类型
  */
  // 注意:这个是错误的写法,当前写法代表闭包的返回值可以是nil
  //var finsh: ()->()?
  // 下面是正确的写法
  var finsh: (()->())?
  override func viewDidLoad() {
  super.viewDidLoad()
  weak var weakSelf = self
  loadata { 
      print("回调")
      // 在swift开发中,能不写self就不写self,但是在闭包中必须写上self
      // 所以以后看到self基本上都是和闭包有关系
      weakSelf!.view.backgroundColor = UIColor.brown
      }
  }
  func loadata(finsh:()->())  {
  print("执行耗时操作")
  finsh()
  }
  override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
  // Dispose of any resources that can be recreated.
 }
}


**循环引用解决:以上面的为例

方式一:

-  使用weak,对当前控制器使用弱引用

- 但是因为self可能有值也可能没有值,因此weakSelf是一个可选类型,在真正使用时可以对其强制解包(该处强制解包没有问题,因为控制器一定存在,否则无法调用所在函数)

weak var weakSelf = self

loadata {

print("回调")
       // 在swift开发中,能不写self就不写self,但是在闭包中必须写上self
       // 所以以后看到self基本上都是和闭包有关系
        weakSelf!.view.backgroundColor = UIColor.brown
        }
      }


方式二:

- 和方案一类型,只是书写方式更加简单

- 可以写在闭包中,并且在闭包中用到的self都是弱引用

loadata { [weak self] () -> () in

print("回调")
            // 在swift开发中,能不写self就不写self,但是在闭包中必须写上self
            // 所以以后看到self基本上都是和闭包有关系
            self!.view.backgroundColor = UIColor.brown
            }
        }
方式三:
 -  使用关键字unowned
 - 从行为上来说 unowned 更像OC中的 unsafe_unretained
 - unowned 表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个 "无效的" 引用,它不能是 Optional 值,也不会被指向 nil
        loadata { [unowned self] () -> () in
            print("回调")
            // 在swift开发中,能不写self就不写self,但是在闭包中必须写上self
            // 所以以后看到self基本上都是和闭包有关系
            self.view.backgroundColor = UIColor.brown
          }
        }


目录
相关文章
|
8月前
|
缓存 JavaScript 前端开发
|
存储 Swift
24 闭包和闭包表达式
闭包和闭包表达式
69 0
|
3月前
|
自然语言处理 JavaScript 前端开发
什么是闭包
【10月更文挑战第12天】什么是闭包
|
4月前
|
移动开发
浅谈H5闭包
浅谈H5闭包
|
5月前
|
存储 自然语言处理 JavaScript
闭包
闭包
19 0
|
JavaScript 前端开发
对闭包的理解以及使用
对闭包的理解以及使用
56 1
|
存储 缓存 前端开发
详解 Reat 中的闭包问题
JavaScript 中的闭包一定是最可怕的特性之一。 即使是无所不知的 ChatGPT 也会告诉你这一点。 它也可能是最隐秘的语言概念之一。 每次编写任何 React 代码时,我们都会用到它,大多数时候我们甚至没有意识到。 但最终还是无法摆脱它们:如果我们想编写复杂且高性能的 React 应用程序,我们就必须了解闭包。
111 0
详解 Reat 中的闭包问题
|
PHP 开发者
匿名函数闭包|学习笔记
快速学习匿名函数闭包
匿名函数闭包|学习笔记
闭包的使用
闭包的使用
76 0
|
自然语言处理 JavaScript
你真的懂闭包么?
前言 本文主要总结一下 到目前为止对闭包的理解. 好几年之前学习闭包的时候模模糊糊,看了网上的一些帖子,理解为:函数内部可以使用函数外部的变量,后面看了你所不知道的JS,以为自己懂了,后面面试的时候又感觉自己不懂了,而今感觉自己真正懂了==,特此记录一下。
136 0

热门文章

最新文章