美文网首页
Swift--闭包

Swift--闭包

作者: mayuee | 来源:发表于2022-08-30 14:00 被阅读0次

    闭包概念
    闭包是一个定义在其他函数(父函数)里面的函数,它拥有对父函数里面变量的访问权,自身的作用域、父作用域和全局作用域
    特点:
    1、闭包是函数,它拥有函数的特点,比如 参数和返回值等
    2、作用域:自身的作用域、父作用域和全局作用域

    闭包表达式:
    参数列表是可选的。
    返回值是可选的,(return type 和 return value)
    参数列表 和 返回值的类型 是 根据上下文推断的。

    { (parameters) -> return type in
        statements
        return value
    }
    

    //定义了一个参数 Int,返回值Int类型的闭包

    var simpleInt : (Int) -> Int = { param in
        return param
    }
    print(simpleInt(20))
    

    //尾随闭包
    //函数尾的参数都是闭包

    func loadData(from picUrl:String, completion:(Data) -> Void, failure:() -> Void){
        if let data = picUrl.data(using: .utf8) {
            completion(data)
        }
        else{
            failure()
        }
    }
    //正常写
    loadData(from:  "http://baidu.com/xxx/xxx.png", completion:{ (data) in
        print("load data finished")
    }, failure: {
        print("load data failured")
    })
    
    //尾闭包。 少写逗号,少写函数名
    loadData(from: "http://baidu.com/xxx/xxx.png") { (data) in
        print("load data finished")
    } failure: {
        print("load data failured")
    }
    
    //闭包参数
    print("1.--------完整写法")
    var names = ["LiLei", "HanMei", "Tom", "Jerry"]
    var reversedNamse = names.sorted { (s1: String, s2: String) -> Bool in
        return s1 > s2
    }
    print(reversedNamse)
    
    print("1.--------省略参数类型")
    names = ["LiLei", "HanMei", "Tom", "Jerry"]
    reversedNamse = names.sorted { (s1, s2) -> Bool in
        return s1 > s2
    }
    print(reversedNamse)
    
    print("3.--------省略返回类型")
    names = ["LiLei", "HanMei", "Tom", "Jerry"]
    reversedNamse = names.sorted { s1, s2 in
        return s1 > s2
    }
    print(reversedNamse)
    
    print("4.--------省略返回类型")
    names = ["LiLei", "HanMei", "Tom", "Jerry"]
    reversedNamse = names.sorted { s1, s2 in
        return s1 > s2   //return也可以省略
    }
    print(reversedNamse)
    
    print("5.--------下标比较")
    names = ["LiLei", "HanMei", "Tom", "Jerry"]
    reversedNamse = names.sorted { $0 > $1 }
    print(reversedNamse)
    
    print("6.--------只有比较符号")
    names = ["LiLei", "HanMei", "Tom", "Jerry"]
    reversedNamse = names.sorted(by: >)
    print(reversedNamse)
    
    
    //闭包的捕获值
    func makeIncrement(forIncrement amount : Int) -> () -> Int {
        var runningTotal = 0
        func incrementer() -> Int{
            runningTotal += amount
            return runningTotal
        }
        //函数作为闭包返回
        return incrementer
    }
    //拿到函数返回的闭包
    let incrementByTen = makeIncrement(forIncrement: 10)
    
    // 返回 10
    print(incrementByTen())
    // 返回 20
    print(incrementByTen())
    // 返回 30
    print(incrementByTen())
    
    ///以下代码说明,闭包 是 引用类型!!
    /// anotherIncrementByTen 和 incrementByTen 指向同一块内存,同一个闭包
    let anotherIncrementByTen = incrementByTen
    //返回 40
    print(anotherIncrementByTen())
    
    // 50
    print(incrementByTen())
    

    逃逸闭包
    当闭包作为参数传递给函数,但在函数返回后被调用时,闭包被称为转义函数。
    当生命一个闭包作为其参数之一的函数时,可以在参数的类型之前写入 @escaping,以指示允许对闭包进行转义。
    即当闭包作为参数传递给函数,但在函数里没有立即调用,而是保存起来,在其他时机、函数之外调用。

    class PictureLoader{
        private var completion: (Data) -> Void
        private var failure: () -> Void
        
        init(completion: @escaping (Data) -> Void, failure: @escaping () -> Void) {
            self.completion = completion
            self.failure = failure
        }
        
        private func loadData(url: String) -> Data?{
            if let data = url.data(using: .utf8) {
                return data
            }
            return Data()
        }
        
        func loadPicture(from picUrl: String) {
            if let picData = loadData(url: picUrl) {
                self.completion(picData)
            }
            else{
                self.failure()
            }
        }
    }
    
    //先实例化,初始化的时候,传入的尾随闭包还没有调用
    var picLoader = PictureLoader { (picture) in
        print(picture)
    } failure: {
        print("下载失败")
    }
    
    picLoader.loadPicture(from: "http://baidu.com/xxx/xxx.png")
    

    //AUTOCLOSURES 自动闭包

    闭包强循环引用
    action 闭包中引用了 self, 而 self 中🈶引用了 action
    形成了闭包强循环引用,Animal 类对象 引用计数不为 0 ,不会被释放
    特别注意: action 多次引用 self, 不会多次增加 self 的引用计数

    class Animal{
        let name: String
        let action: String?
        
        //懒加载 闭包类型的成员属性
        lazy var doSomeThing: () -> String = {
            if let action = self.action {
                return "\(self.name) will \(action)), \(self.name) will \(action))"
            }
            else{
                return "\(self.name)"
            }
        }
        
        init(name: String, action: String? = nil) {
            self.name = name
            self.action = action
        }
        
        deinit {
            print("\(name) 销毁")
        }
    }
    
    //不会打印销毁
    var animal: Animal? = Animal(name: "Dog", action: "run")
    print(animal!.doSomeThing())
    animal = nil
    
    print("--------解决闭包强循环")
    //用不用 weak,判断闭包是不是类属性,是类的属性的时候才可能造成循环引用
    // 方法内的临时闭包不会造成循环引用,不用 weak
    class NameClass{
        var name: String
        init(name: String) {
            self.name = name
        }
    }
    class Animal2{
        let name: String
        let action: String?
        
        //一个 NameClass 类 属性
        let nameObject = NameClass(name: "Cat")
        
        //懒加载 闭包类型的成员属性
        lazy var weakDoSomeThing: () -> String = {
            [weak self] in  //使用weak解决循环引用
            if let action = self?.action {
                return "\(self?.name) will \(action)), \(self?.name) will \(action))"
            }
            else{
                return "\(self?.name ?? <#default value#>)"
            }
        }
        
        lazy var unownedDoSomeThing: () -> String = {
            [unowned self] in  //使用无主引用 unowned 解决循环引用
            if let action = self.action {
                return "\(self.name) will \(action)), \(self.name) will \(action))"
            }
            else{
                return "\(self.name)"
            }
        }
        
        lazy var doSomeThing1: () -> String = {
            //这里捕获类别定义,不增加 Animal2 对象 和 nameObj 对象的 引用计数
            // doSomeThing 这个函数和 nameObject 没有从属关系,所以避免干扰用 weak 就可以,
            [unowned self, weak nameObject = self.nameObject] in
            guard let nameObj = nameObject else {
                return ""
            }
            
            if let action = self.action {
                return "\(nameObj.name) will \(action)), \(nameObj.name) will \(action))"
            }
            else{
                return "\(nameObj.name)"
            }
        }
        
        lazy var doSomeThing2: () -> String = {
            //这里捕获类别定义,不增加 Animal2 对象 和 nameObj 对象的 引用计数
            [unowned self] in
            if let action = self.action {
                return "\(self.nameObject.name) will \(action), \(self.nameObject.name) will \(action)"
            }
            else{
                return "\(self.nameObject.name)"
            }
        }
        
        init(name: String, action: String? = nil) {
            self.name = name
            self.action = action
        }
        deinit {
            print("\(name) 销毁")
        }
    }
    
    //不会打印销毁
    var animal2: Animal2? = Animal2(name: "Dog", action: "run")
    print(animal2!.doSomeThing2())
    animal2 = nil
    
    

    相关文章

      网友评论

          本文标题:Swift--闭包

          本文链接:https://www.haomeiwen.com/subject/kpmlnrtx.html