美文网首页iOS DevelopmentiOS点点滴滴
Swift的闭包和OC的Block里值的捕获的区别

Swift的闭包和OC的Block里值的捕获的区别

作者: iPhone贴膜小哥 | 来源:发表于2018-03-05 20:05 被阅读18次

    看一段OC代码

        NSInteger i = 1;
        void(^block)(void) = ^{
            NSLog(@"block %ld:", i);
        };
        i += 1;
        NSLog(@"out1 %ld:", i);
        block();
        NSLog(@"out2 %ld:", i);
    

    打印


    oc.png

    在OC里,编译器走到第三行的时候,实际上已经对i进行了拷贝,可以理解成

    NSInteger iCopy = i
    

    所以block里的值和外面的值是不会互相影响的。
    如果想要里外一致,则需要通过添加 __block关键字,在block里仅仅只是I的指针,拷贝也只是指针的拷贝,这里不详细讨论此关键字以及循环引用相关。


    看一段Swift代码

            var i = 1
            let closure = {
                print("closure \(i)")
            }
            i += 1
            print("out1 \(i)")
            closure()
            print("out 2 \(i)")
    

    代码和OC一毛一样,打印的结果是


    swift

    swift指的捕获是在执行的时候再捕获,当代码执行到 closure(),对值进行捕获,i的值是2,所以打印闭包里的i等于2

    修改值
    在OC里修改值基本数据类型__block, OC-Obj类型__weak
    在Swift里,看如下代码

     var i = 1
            let closure = {
                i += 1
                print("closure \(i)")
            }
            i += 1
            print("out1 \(i)")
            closure()
            print("out 2 \(i)")
    

    在闭包里多了一行 *** i += 1*** 编译,没有警告,运行结果如下

    image.png
    也就是说,在swift里,闭包就像是oc给外部变量默认添加了block或者__weak

    Swift里实现和OC一样的值捕获,这种实现在Swift里叫捕获列表,capturing list
    看如下代码

    var i = 1
            let closure = {
                [i] in
                print("closure \(i)")
            }
            i += 1
            print("out1 \(i)")
            closure()
            print("out 2 \(i)")
    

    闭包内部多了一行*** [i] in*** 语法为中括号[]里面添加捕获的变量,然后用in 分割上下分。打印结果为


    image.png

    类似于刚开始的OC代码,Swift内部,类似执行了这样的一行代码

    let iCopy = i
    

    最后

    大家都说Swift里的闭包和OC里的block一样,在值的捕获这里是有很大的不一样的。

    相关文章

      网友评论

        本文标题:Swift的闭包和OC的Block里值的捕获的区别

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