13.闭包(特殊的函数)

  • 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

          }
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 介绍 Swift官方开发文档对于闭包的介绍是这样的:闭包是可以在代码中被传递和引用的功能性独立模块。Swift 中...
    Latte_Bear阅读 4,351评论 0 1
  • Swift 介绍 简介 Swift 语言由苹果公司在 2014 年推出,用来撰写 OS X 和 iOS 应用程序 ...
    大L君阅读 8,584评论 3 25
  • 在上一篇文章Swift中的变量和常量中我总结了一些自己对于变量和常量的认识,最近学习了闭包,顺便给大家分享一下关于...
    老板娘来盘一血阅读 18,830评论 16 87
  • "闭包,Swift中的新概念,然而除了写法不同,实际上用法与用途都和OC中的Block没什么不同" 闭包 Swif...
    S_Lyu阅读 3,698评论 0 15
  • 使用playground来测试代码很有意思 Xcode 7.2 如果项目名称包含中文和数字 在数组中添加元素 会造...
    一黑阅读 3,828评论 0 0

友情链接更多精彩内容