Swift - defer的注意点

defer:用来定义以任何方式(抛错误、return等)离开代码块前必须要执行的代码,这块代码将延迟至当前作用域结束之前执行。

基本使用

func test() {
    print("run test 1")
    
    defer {
        print("run defer")
    }
    
    print("run test 2")
}

// run test 1
// run test 2
// run defer

注意点

  1. 一个函数中可以有多个defer,同一作用域的defer都是以栈的形式添加的,是以先进后出的顺序执行

  2. defer可以被阻拦添加(例如添加新defer前就 return 了)

  3. defer可以嵌套

    • 如果其中一层作用域的defer里面有多个子defer,那么这一层作用域结束之前,同样也是以先进后出的顺序去执行里面的子defer
var isAdd = true

func test() {
    print("run test 1")
    
    defer {
        print("run defer 5")
    }
    
    // defer可以嵌套
    defer {
        // 执行这一层作用域时同样也是以先进后出的顺序去执行里面的子defer
        defer {
            print("run defer 4")
        }
        
        defer {
            print("run defer 3")
        }
        
        print("run defer 2")
    }

    // defer可以被阻拦添加
    guard isAdd else { return }
    
    defer {
        print("run defer 1")
    }
    
    print("run test 2")
}

// isAdd == true
// run test 1
// run test 2
// run defer 1
// run defer 2
// run defer 3
// run defer 4
// run defer 5

// isAdd == false
// run test 1
// run defer 2
// run defer 3
// run defer 4
// run defer 5
  1. defer除了可以访问当前作用域的任意变量,也可以访问所有外层作用域中的任意变量(最外层则是函数体)
    • 这些变量并不是copy过来的,而是有引用关系的,是真的把变量传过来的;
    • 而所有内层作用域中的变量都无法访问。
func test() {
    defer {
        defer {
            defer {
                defer {
                    let e = 5
                    d += 1
                    c += 1
                    b += 1
                    a += 1
                    // 可以访问当前和所有外层作用域的任意变量
                    print("a: \(a),", "b: \(b),", "c: \(c),", "d: \(d),", "e: \(e)")
                }
                var d = 4
                c += 1
                b += 1
                a += 1
            }
            var c = 3
            b += 1
            a += 1
        }
        var b = 2
        a += 1
    }
    var a = 1
    // 无法访问内层作用域的变量
    // b += 1
}

// a: 5, b: 5, c: 5, d: 5, e: 5

THE END.

你可能感兴趣的:(Swift - defer的注意点)