美文网首页iOS面试专项
iOS中的Block , Stack, Heap

iOS中的Block , Stack, Heap

作者: joshualiyz | 来源:发表于2019-04-02 21:05 被阅读0次

    复习下block和内存相关的知识

    Stack(栈) & Heap(堆)

    栈的读写速度比堆快,这就解释了为什么方法中的变量会分配到栈空间。
    一般而言,代码中被{}包含的区间变量都存储在栈中,当这一区间执行结束的时候,所有区间变量都会被系统自动释放,所以栈中的对象无法被外界retain
    堆用来存储对象Object,我们需要自己释放堆中的对象(ARC只是让编译器帮我们做了而已)。
    内存泄漏发生在堆上,当堆上分配的内存空间没有被显示释放的时候,泄漏就发生了。
    不同的应用有不同的堆空间,不同的线程有不同的栈,同一应用中的不同线程通过堆来共享数据。

    Block

    Block是唯一分配在栈上的对象
    栈中存储的内容一般是一些定长的变量,比如intbool对象地址等。Block也是确定长度的,一个Block被创建之后就无法再修改。
    当Block所在的区间执行结束,它就会被释放,我们知道栈中的对象无法被retain,那么怎么传递Block呢?
    答案是将Block拷贝到堆上。
    这就是为什么我们经常用copy来修饰Block变量
    @property (copy, nonatomic) void (^block) ();

    当对Block第一次使用copy的时候,Block会被拷贝到堆上;对其后续的copy并不会拷贝多次,只会增加引用计数。
    strong修饰Block并不会拷贝,如果Block是存储在栈上的,这个strong对象可能会成为一个野指针

    Block循环引用

    常见的Block循环应用便是在Block代码区间中持有了self
    这里需要注意的是:如果Block只是在栈上,当它执行结束之后系统会自动释放其内部变量,所以并不会发生内存泄漏。
    不过我们遇到的Block经常会被传递,也就是存储在堆上,这时候就需要用weak-strong-dance来处理了。

    __block

    Block存储在栈上,所以Block会将它用到的所有外部变量进行拷贝,这也就是为什么在Block中修改外部变量的值不会生效(修改指针指向的内容另当别论)。
    __block做的事情就是如果这个变量在Block中被捕获,那么就将这个变量拷贝到堆上,这样一来就可以修改了。

    相关文章

      网友评论

        本文标题:iOS中的Block , Stack, Heap

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