美文网首页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