精华内容
下载资源
问答
  • block 本身是像对象一样可以retain和release。但是,block在创建的时候,它的内存是...使用retaim也可以,但是block的retain行为默认是用copy的行为实现, 因为block变量默认是生命在栈变量的,为了能够在block的声

    block 本身是像对象一样可以retain和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。它本身的作用域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致崩溃。

    使用retaim也可以,但是block的retain行为默认是用copy的行为实现,

    因为block变量默认是生命在栈变量的,为了能够在block的声明域外使用,所以要把block拷贝copy一份到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。


    __block的作用

    在block的{ } 体内,是不可以对外面的变量进行更改的,使用__block就能改变block块中的变量值,

    __block和__weak有什么区别?

    __block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。

    __weak只能在ARC模式下 使用,也只能修饰对象,不能修饰基本数据类型。

    __block对象可以在block中被重新赋值,__weak不可以。

    本文参考自http://blog.csdn.net/www9500net_/article/details/52397873

    展开全文
  • iOS block修饰符用copy还是strong

    千次阅读 2020-10-20 10:59:29
    Block简介: block其实就是一个代码块,把你想要执行的代码封装在这个代码块里,等到需要的时候再去调用。那block是OC对象吗?答案是肯定的 ...使用retain也可以,但是block的retain行为默认是用copy的行为实..
    • Block简介:

      block其实就是一个代码块,把你想要执行的代码封装在这个代码块里,等到需要的时候再去调用。那block是OC对象吗?答案是肯定的

    • Block修饰符选择:

      block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。

      使用retain也可以,但是block的retain行为默认是用copy的行为实现的,

      因为block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。

    • 相关文章:
      Block分为全局Block、堆Block和栈Block

    展开全文
  • Linux编程点击右侧关注,免费入门到精通!作者丨彭序猿https://www.jianshu.com/p/4db3b4f1d522前言Block 在平时开发中经常使用,...

    640?wx_fmt=gif

    640?wx_fmt=jpeg

    Linux编程 点击右侧关注,免费入门到精通! 640?wx_fmt=jpeg



    作者丨彭序猿
    https://www.jianshu.com/p/4db3b4f1d522


    640?wx_fmt=gif

    前言


    Block 在平时开发中经常使用,它是 Objective-C 对 闭包 是实现,定义如下:


    Block 是一个里面存储了指向定义 block 时的代码块的函数指针,以及block外部上下文变量信息的结构体。

    简单来说就是:带有自动变量的匿名函数。


    本篇文章不会阐述 Block 的使用语法,有需要了解 Block 语法可以查看文末的参考链接。本文主要通过学习 Block 源代码来了解 Block 实现原理、内存相关知识、以及如何截获外部变量,然后再通过一些常见的 Block 面试题,进一步加深对 Block 的理解。


    640?wx_fmt=gifBlock 对象内存相关知识


    iOS 内存分布,一般分为:栈区、堆区、全局区、常量区、代码区。其实 Block 也是一个 Objective-C 对象,常见的有以下三种 Block:


    NSMallocBlock :存放在堆区的 Block

    NSStackBlock  : 存放在栈区的 Block

    NSGlobalBlock : 存放在全局区的 Block

    通过代码实验(声明 strong、copy、weak 修饰的 Block,分别引用全局变量、全局静态变量、局部静态变量、普通外部变量) ,得出初步的结论:


    1.Block 内部没有引用外部变量,Block 在全局区,属于 GlobalBlock

    2.Block 内部有外部变量:


    a.引用全局变量、全局静态变量、局部静态变量:Block 在全局区,属于 GlobalBlock


    b.引用普通外部变量,用 copy,strong 修饰的 Block 就存放在堆区,属于 MallocBlock;用 weak 修饰的Block 存放在栈区,属于 StackBlock


    注意:Block 引用普通外部变量,都是在栈区创建的,只是用 strong、copy 修饰的 Block 会把它从栈区拷贝到堆区一份,而 weak 修饰的 Block 不会;


    通过上面可以知道,在 ARC 中,用 strong、copy 修饰的 Block,会从栈区拷贝到堆区,所以在 ARC 中,用 strong 修饰和 copy 修饰的 Block 效果是一样的;


    640?wx_fmt=gifBlock 源代码分析


    640?wx_fmt=gif利用 Clang 将 Objective-C 代码转换成 C++ 代码


    通过 clang 命令将 Objective-C 代码转换成 C++ 代码,可以了解其底层机制,有助于我们更加深刻的认识其实现原理。下面是 clang 相关命令:


    //1.最简单的命令:
    clang -rewrite-objc mian.m

    //2.但是如果遇到 main.m:9:9: fatal error: 'UIKit/UIKit.h' file not found 类似的错误需要我们指定下框架
    xcrun -sdk iphonesimulator11.4 clang -S -rewrite-objc -fobjc-arc -fobjc-runtime=ios-11.4 main.m

    //3.展示 SDK 版本命令
    xcodebuild -showsdks


    640?wx_fmt=gif通过源码断点调试 Block


    上面 clang 命令只是将 Objective-C 代码转换成 C++ 代码,但是有时候我们想进一步了解 Block 整个的执行过程,我们可以通过 Block 底层源码一步一步断点来研究 Block 的执行过程。


    1.首先我们可以去官网上面下载 Block 源代码:

    https://opensource.apple.com/source/libclosure/libclosure-65/


    2.然后将源码中缺少的库添加进入工程,具体操作可以参考这篇 Blog:

    https://blog.csdn.net/WOTors/article/details/54426316


    通过上面两个步骤,我们就有一个包含 Block 源码的工程,然后可以编写 Block 代码,去断点观察 Block 具体的执行过程。

    配置工程还是比较麻烦的,这里我上传了一份:BlockSourceCode

    https://github.com/pengxuyuan/PXYFMWK/tree/master/BlockSourceCode


    640?wx_fmt=gif分析简单的 Block C++ 源代码


    首先我们通过 clang 将 Block Objective-C 代码转换成以下 C++ 代码,下面是主要代码:


    struct __block_impl {
        void *isa;
        int Flags;
        int Reserved;
        void *FuncPtr;
    };

    static struct __block_desc_0 {
        size_t reserved;
        size_t Block_size;
    } _block_desc_0_DATA = { 0sizeof(struct __block_desc_0)};

    struct _block_impl_0 {

        struct __block_impl impl;
        struct __block_desc_0Desc;
        int i; // 这个是引用外部变量 i
        _block_impl_0(void *fp, struct __block_desc_0 *desc, int _i, int flags=0) :i(_i){

            impl.Flags = flags;
            impl.FuncPtr = fp;
            Desc = desc;
        }
    };


    通过分析上面源码,我们可以得到下面几点结论:


    1.结构体中有 isa 指针,证明 Block 也是一个对象


    2.Block 底层是用结构体来实现的,结构体 _block_impl_0  包含了 __block_impl  结构体和 __block_desc_0  结构体。


    3.__block_impl  结构体中的 FuncPtr 函数指针,指向的就是我们的 Block 的具体实现。真正调用 Block 就是利用这个函数指针去调用的。


    4.为什么能访问外部变量,就是因为将外部变量复制到了结构体中(上面的 int i),即自动变量会作为成员变量追加到 Block 结构体中。


    640?wx_fmt=gif分析具有 __block 修饰符外部变量的 Block 源代码


    我们知道 Block 截获外部变量是将外部变量作为成员变量追加到 Block 结构体中,但是匿名函数存在作用域的问题,这个就是为什么我们不能在 Block 内部去修改普通外部变量的原因。所有就出现了 __block 修饰符来解决这个问题。


    下面我们来看下 __ block 修饰的变量转换成 C++ 代码是什么样子的。


    //Objective-C 代码
     - (void)blockDataBlockFunction {
     __block int a = 100;  ///在栈区
     void (^blockDataBlock)(void) = ^{
     a = 1000;
     NSLog(@"%d", a);
     };  ///在堆区
     blockDataBlock();
     }

    //C++ 代码
    struct __Block_byref_a_0 {
      void *__isa;
    __Block_byref_a_0 *__forwarding;
     int __flags;
     int __size;
     int a;
    };

    struct __BlockStructureViewController__blockDataBlockFunction_block_impl_0 {
      struct __block_impl impl;
      struct __BlockStructureViewController__blockDataBlockFunction_block_desc_0Desc;
      __Block_byref_a_0 *a; // by ref
    };


    具有 __block 修饰的变量,会生成一个 Block_byref_a_0 结构体来表示外部变量,然后再追加到 Block 结构体中,这里生成 Block_byref_a_0 这个结构体大概有两个原因:一个是抽象出一个结构体,可以让多个 Block 同时引用这个外部变量;另外一个好管理,因为 Block_byref_a_0 中有个非常重要的成员变量 forwarding  指针,这个指针非常重要(这个指针指向 Block_byref_a_0 结构体),这里是保证当我们将 Block 从栈拷贝到堆中,修改的变量都是同一份。


    forwarding  指针存在的理由,我们可以看 Block 存储域一节。


    640?wx_fmt=gifBlock 是如何解决存储域问题


    首先我们知道 Block 底层是用结构体,Block 会转换成 block 结构体,__block 会转换成 __block 结构体。


    然后 block 没有截获外部变量、截获全局变量的都是属于全局区的 Block,即 GlobalBlock;其余的都是栈区的 Block,即 StackBlock;

    对于全局区的 Block,是不存在作用域的问题,但是栈区 Block 不同,在作用域结束后就会 pop 出栈,__block 变量也是在栈区的,同理作用域结束也会 pop 出栈。


    为了解决作用域的问题,Block 提供了 Copy 函数,将 Block 从栈复制到堆上,在 MRC 环境下需要我们自己调用 Block_copy  函数,这里就是为什么 MRC 下,我们为什么需要用 copy 来修饰 Block 的原因。


    然而在 ARC 环境下,编译器会尽可能给我们自动添加 copy 操作,这里为什么说尽量呢,因为有些情况编译器无法判断的时候,就不会给我们添加 copy 操作,这里就需要我们自己主动调用 copy 方法了。


    640?wx_fmt=gif__block  变量的存储域


    Block 从栈复制到堆上,__block 修饰的变量也会从栈复制到堆上;为了结构体 __block 变量无论在栈上还是在堆上,都可以正确的访问变量,我们需要 forwarding 指针;


    在 Block 从栈复制到堆上的时候,原本栈上结构体的 forwarding 指针,会改变指向,直接指向堆上的结构体。这样子就可以保证之后我们都是访问同一个结构体中的变量,这里就是为什么 __block 修饰的变量,在 Block 内部中可以修改的原因了。


    640?wx_fmt=gifBlock 截获对象需要管理对象的生命周期


    我们知道 Block 引用外部变量会将其追加到结构体中,但是编译器是无法判断 C 语言结构体的初始化和废弃的,因此在 __block_desc_0 会增加成员变量 copy 和 dispose;以及 block_copy、block_dispose 函数。


    用来 Block 从栈复制到堆、堆上的 Block 废弃的时候分别调用。


    640?wx_fmt=gifBlock 会出现循环引用


    对于 Block 循环引用算是经典问题了,当 A 持有 B,B 又持有 A,这个时候就会出现循环引用。Block 对于外部变量都会追加到结构体中,所以在实现 Block 时候需要注意这个问题。


    ARC 环境一般我们用 __weak 来打破,MRC 环境的话,我们可以使用 __block 来打破循环引用。


    640?wx_fmt=gifBlock 面试题


    640?wx_fmt=gif1. 下面代码在 MRC 环境 和 ARC 环境运行的情况


    void exampleA() {
      char a = 'A';
      ^{
        printf("%cn", a);
      }();
    }

    //调用:exampleA();


    答:首先这个 Block 引用了普通外部变量,所以这个 Block 是在栈上面创建的;Block 是在 exampleA() 函数内创建的,然后创建完马上调用,这个时候  exampleA() 并没有执行完,所以这个栈 Block 是存在的,不会被 pop 出栈。故在 MRC 和 ARC 上面都可以正确执行。


    640?wx_fmt=gif2. 下面代码在 MRC 环境 和 ARC 环境运行的情况


    void exampleB_addBlockToArray(NSMutableArray *array) {
      char b = 'B';
      [array addObject:^{
        printf("%cn", b);
      }];
    }

    void exampleB() {
      NSMutableArray *array = [NSMutableArray array];
      exampleB_addBlockToArray(array);
      void (^block)() = [array objectAtIndex:0];
      block();
    }

    //调用:exampleB();


    答:这个跟第一题区别就是将 Block 的创建放到一个函数中去。同理分析:exampleB_addBlockToArray 中创建的 Block 也是引用了普通外部变量,Block 创建在栈上。


    MRC 环境上,调用 exampleB_addBlockToArray  函数,会创建一个栈 Block 存放到数组中去,然后 exampleB_addBlockToArray  函数结束,Block 被 pop 出栈,这个时候再去调用 Block,Block 已经被释放了,故出现异常,不能正确执行。


    ARC 环境下,在 NSMutableArray 的 addObject 方法中,编译器会自动执行 Copy 操作,将 Block 从栈拷贝到堆(StackBlock -> MallocBlock),故在 ARC 环境可以正确执行。


    修改方案如下:


    // 主动调用 copy 方法,将 Block 从栈拷贝到堆中,Block_copy(<#...#>)
    [array addObject:[^{
        printf("%cn", b);
    } copy]];


    640?wx_fmt=gif3. 下面代码在 MRC 环境 和 ARC 环境运行的情况


    void exampleC_addBlockToArray(NSMutableArray *array) {
      [array addObject:^{
        printf("Cn");
      }];
    }

    void exampleC() {
      NSMutableArray *array = [NSMutableArray array];
      exampleC_addBlockToArray(array);
      void (^block)() = [array objectAtIndex:0];
      block();
    }

    //调用:exampleC();


    答:exampleC_addBlockToArray 中的 Block 并没有引用外部变量,所以 Block 是创建在全局区的,是一个 GlobalBlock,生命周期是跟随着程序的,故 MRC、ARC 环境下都可以正确运行。


    640?wx_fmt=gif4. 下面代码在 MRC 环境 和 ARC 环境运行的情况


    typedef void (^dBlock)();
    dBlock exampleD_getBlock() {
      char d = 'D';
      return ^{
        printf("%cn", d);
      };
    }
    void exampleD() {
      exampleD_getBlock()();
    }
    //调用:exampleD();


    答:这题跟第二题差不多,区别在于这里是将 Block 作为函数返回值了;一样栈区 Block 在 exampleD_getBlock 函数执行完就会释放,MRC 环境下会调用异常,但是这里编译器能检查到这种情况,这里实际效果是编译不通过。


    在 ARC 环境下,Block 作为函数返回值,会自动调用 Copy 方法,将 Block 从栈复制到堆上(StackBlock -> MallocBlock),故 ARC 环境下可以正确运行。


    640?wx_fmt=gif5. 下面代码在 MRC 环境 和 ARC 环境运行的情况


    typedef void (^eBlock)();
    eBlock exampleE_getBlock() {
      char e = 'E';
      void (^block)() = ^{
        printf("%cn", e);
      };
      return block;
    }
    void exampleE() {
      eBlock block = exampleE_getBlock();
      block()
    }
    //调用:exampleE();


    答:这题跟第四题是一样的,这里在 MRC 环境下,可以编译通过,但是调用异常;ARC 环境下可以正确执行。


    640?wx_fmt=gif6. ARC 环境下输入结果


    __block NSString *key = @"AAA";

        objc_setAssociatedObject(self, &key, @1, OBJC_ASSOCIATION_ASSIGN);
        id a = objc_getAssociatedObject(self, &key);

        void (^block)(void) = ^ {
            objc_setAssociatedObject(self, &key, @2, OBJC_ASSOCIATION_ASSIGN);
        };

        id m = objc_getAssociatedObject(self, &key);
        block();
        id n = objc_getAssociatedObject(self, &key);
        objc_setAssociatedObject(self, &key, @3, OBJC_ASSOCIATION_ASSIGN);
        id p = objc_getAssociatedObject(self, &key);
        NSLog(@"%@ --- %@ --- %@ --- %@",a,m,n,p);


    答:输入结果:1 --- (null) --- 2 --- 3,代码执行过程如下:


    1.__block 修饰的 key,创建在栈区,访问变量 key 为:&(结构体->forwarding->key) ,key 在栈区,此时利用栈区地址作为 Key 来存值


    2.变量 a 使用栈区地址取值,故 a 的值为 1


    3.声明一个 block,引用到了外部变量 key,此时将 block 从栈拷贝堆,访问变量 key 为:&(结构体->forwarding->key) ,key 在堆区


    4.变量 m 用堆区地址来取值,故为 null


    5.执行 block,用堆区地址将 2 存进去


    6.变量 n 用堆区地址来取值,故为 2


    7.再用堆区地址将 3 存进去


    8.变量 p 用堆区地址来取值,故为 3


    640?wx_fmt=gif7. 有几种方式去调用 Block


    void (^block)(void) = ^{
     NSLog(@"block get called");
     };

     //1. blcok()
     block();

     //2. 利用其它方法去执行 block
     [UIView animateWithDuration:0 animations:block];

     //3.
     [[NSBlockOperation blockOperationWithBlock:block] start];

     //4. NSInvocation
     NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:"v@?"];
     NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
     [invocation invokeWithTarget:block];

     //5.DLIntrospection invoke
     [block invoke];

     //6. 指针调用
     void *pBlock = (__bridge void *)block;
     void (*invoke)(void *, ...) = *((void **)pBlock + 2);
     invoke(pBlock);

     //7. 利用 Clang
     __strong void(^cleaner)(void) __attribute ((cleanup(blockCleanUp),unused)) = block;


     //8. 内联一个汇编 完成调用
     asm("callq *0x10(%rax)");

     static void blockCleanUp (__strong void (^*block)(void)) {
     (*block)();
     }


    640?wx_fmt=gif8. 如何通过 Block 实现链式编程风格的代码


    具体可看实现:Block ChainProgramming

    https://github.com/pengxuyuan/PXYFMWK/blob/master/PXYFMWK/PXYFMWK/PXYFMWK/PXYFMWK/Component/PXYChainProgramming/UIView/UIView%2BPXYChainProgramming.m


    640?wx_fmt=gifBlock 为什么用 Copy 修饰


    对于这个问题,得区分 MRC 环境 和 ARC 环境;首先,通过上面小节可知,Block 引用了普通外部变量,都是创建在栈区的;对于分配在栈区的对象,我们很容易会在释放之后继续调用,导致程序奔溃,所以我们使用的时候需要将栈区的对象移到堆区,来延长该对象的生命周期。


    对于 MRC 环境,使用 Copy 修饰 Block,会将栈区的 Block 拷贝到堆区。


    对于 ARC 环境,使用 Strong、Copy 修饰 Block,都会将栈区的 Block 拷贝到堆区。


    所以,Block 不是一定要用 Copy 来修饰的,在 ARC 环境下面 Strong 和 Copy 修饰效果是一样的。


    640?wx_fmt=gif

    总结


    这里我们用比较浅显的角度分析了 Block,了解了 Block 也是一个对象,有对应的内存分布;同时作为匿名函数,也会存在作用域的问题,也了解了 Block 是如何截获外部变量的。


    对于面试题,主要还是要判断作用域的问题,栈区的 Block 是否复制到堆区中。


     推荐↓↓↓ 

    640?wx_fmt=png

    ?16个技术公众号】都在这里!

    涵盖:程序员大咖、源码共读、程序员共读、数据结构与算法、黑客技术和网络安全、大数据科技、编程前端、Java、Python、Web编程开发、Android、iOS开发、Linux、数据库研发、幽默程序员等。

    展开全文
  • 相信有很多面试者被问到这样的问题:block使用什么修饰,往往能够答出是copy,很多面试官就会问到:为什么使用copy,这时候就懵了。我亲身体验了一把,所以先总结一下。block本身是像对象一样可以retain,和...

    相信有很多面试者被问到这样的问题:block使用什么修饰,往往能够答出是copy,很多面试官就会问到:为什么要使用copy,这时候就懵了。
    我亲身体验了一把,所以先总结一下。

    block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈上的,而不是在堆上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。因为栈区的特点就是创建的对象随时可能被销毁,一旦被销毁后续再次调用空对象就可能会造成程序崩溃,在对block进行copy后,block存放在堆区.
    使用retain也可以,但是block的retain行为默认是用copy的行为实现的,
    因为block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。

    展开全文
  • iOS block为什么用copy

    千次阅读 2017-09-10 12:10:30
    // 联系人 ..., 使用copy与strong其实都一样, 因为block的retain就是用copy来实现的, 所以block使用copy还能装装逼, 说明自己是从MRC下走过来的 谢谢!!!
  • 一、我们在声明Block的时候为什么用Copy来修饰  Block在创建的时候,系统分配内存是在栈区,并没有在堆区;在栈区之外调用BLock将会导致崩溃。所以为了能够在Block的声明作用域之外调用,所以要用block拷贝到堆区...
  • IOS Block copy 传参

    2018-10-30 17:51:10
    @property (copy, nonatomic) void (^backSelectClick)(NSString * custonValue, NSInteger index); void 返回参数. backSelectClick block名字. block返回参数.
  • iOSBlock为什么用copy修饰

    千次阅读 2017-08-16 16:01:14
    默认情况下,block是存档在栈中,可能被随时回收,通过copy操作可以使其在堆中保留一份, 相当于一直强引用着, 因此如果block中用到self时, 需要将其弱化, 通过__weak或者__unsafe_unretained. 以下是示例代码及其...
  • IOS中,block块是新添加的语法,其他程序语言中也被称为闭包。程序块的理念是像任何其他C语言类型一样对待特定的代码块。程序块可以分配给一个变量,以参数的形式传递给函数或方法,当然也可以执行(不同于其他大...
  • 在完成项目期间,不可避免的会使用block,因为block有着比delegate和notification可读性更高,而且看起来代码也会很简洁。于是在目前的项目中大量的使用block。  但是在开发的时候,有时候由于疏忽大意或者一些...
  • iOS用copy修饰Block

    千次阅读 2016-12-12 14:57:05
    Block的三个类型: 1._NSConcreteGlobalBlock,全局的静态block,不会访问外部的变量。就是说如果你的block... 保存在堆中的 block,当引用计数 0 时会被销毁。 3._NSConcreteStackBlock 保存在栈中的 bl
  • 在实际开发中,发现使用Block有着比delegate和notification更简洁的优势。于是在目前的项目中大量的使用block。  在我的头文件我是这样声明使用block的。 [plain] view plaincopy @interface ...
  • 第一部分:Block本质 block 是Cocoa/Cocoa Touch Framework 中的匿名函式(Anonymous Functions)的实作。所谓的匿名函式,就是一段 具有物件性质的程式码,这一段程式码可以当做函式执行,另一方面,又可以当做...
  • iOS block相关:weakSelf和block copy

    千次阅读 2014-12-09 13:45:20
    当在block中调用self的方法时:__weak __typeof(&*self)weakSelf = self; 当在block使用参数传进来的block时:需要将参数block copy
  • ios-block作为属性的时候为什么用copy

    千次阅读 2017-08-09 16:30:36
    当我们block的属性用copy的时候就会把栈的block变成了堆的block。如果我们block用assign来修饰的话就是栈的block,一调用就会出错比如说这样的话一调用就会出错。因为我们是在test方法中赋值的,当方法执行完成之后...
  • Block 为什么用copy属性

    千次阅读 2016-04-04 23:45:58
    Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC下返回Block)。 另一个需要注意的问题是关于线程安全,在声明...
  • 概念 代码块block是苹果在iOS4开始引入的对C语言的扩展,用来实现匿名函数的特性,block是一种特殊的数据类型,其可以正常定义变量、作为参数、作为返回值,...如果我们使用block作为一个对象的属性,我们会使用关键字copy
  • 到这个阶段,我们C的结构编译的代码以及源码能看到Block结构体内部的isa指针是指向_NSContreteStackBlock 的,其实这只是其中的一种,分别还有_NSContreteGlobalBlock 和 _NSContreteMallocBlock,可以根据命名的...
  • iOS Block 基本使用

    千次阅读 2017-01-05 11:38:47
    block是一个数据类型, 多用于参数传递, 代替代理方法, (有多个参数需要传递或者多个代理方法需要实现还是推荐使用代理方法), 少用于当做返回值传递。 block是一个OC对象, 它的功能是保存代码片段, 预先准备好代码...
  • NSstring为什么使用copy copy的深度解析

    千次阅读 2018-04-27 17:23:37
    面试中经常问到的一个题,如果只是答到copy就是会单独复制一份,重新开辟一个地址空间。不会因为原值的修改而修改。这样回答100分只是拿到了10分。面试官会进一步追问。直到问到你不会。。。入门的回答以后,递进...
  • iOS block使用总结

    2015-10-22 09:16:40
    block 声明 : int (^myblock)(int a); [cpp] view plaincopy int (^myblock)(int a);
  • 隐藏的三种Block本体以及为什么使用copy修饰符 __blockBlock的循环引用 上面几个是之前看书记录的知识点,可以回顾下,下面用人话概括下自己的理解,方便以后参考,先记住一个概念,Block就是一个对象 OC ...
  • iOS block简介

    千次阅读 2019-02-16 15:59:07
    BlockiOS 4 才引入的C语言扩充功能。 block什么block 就是带有自动变量(就是局部变量)值的匿名函数。顾名思义就是带有自动变量(也就是局部变量)值的不带名称的函数。 自动变量值是啥意思呢? 先回顾下...
  • iOS为什么block用copy来修饰

    千次阅读 2015-11-28 22:29:11
    Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC下返回Block)。 另一个需要注意的问题是关于线程安全,在声明...
  • iOSiOS Block基本用法记录

    千次阅读 2019-08-12 17:34:05
    做了大半年IOS,每次想写block的时候都发现不记得格式,总要翻一翻老代码然后copy一份,然而并不能记住,恶性循环影响工作效率。 参考:https://www.jianshu.com/p/e82bc3acc2c9记录一下block的基本用法,目标是...
  • iOS Block 底层原理

    2019-07-18 02:02:37
    Block 结构体写法 struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; int ag...
  • 什么BlockBlock是将函数及其执行上下文封装起来的对象。 比如: NSInteger num = 3; NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){ return n*num; }; block(2); 通过clang -rewri....
  • 当一个对象的引用计数0时,这个对象就会被释放。铭记以上两点,我们开始来探讨。 换句话说,如果一个对象,没有强指针指向,就会被释放。举个很形象的例子,假如每一个对象都是一只狗,每一个强指针都是狗链子,狗...
  • ios block传值

    2016-01-19 14:42:03
    iOS block传值 首先创建两个视图控制器,在第一个视图控制器中创建一个UILabel和一个UIButton,其中UILabel是为了显示第二个视图控制器通过block传过来的值。button是点击跳转到第二个控制器。 第二个控制器 里面...
  • iOS Block的内存管理

    2020-04-14 23:27:47
    __block与__weak对于block在ARC下...此时block内部对于__Block包装的对象强持有,ARC如果对于当前Block有强引用,则会将当前block从栈copy到堆上,此时如果之前变量在栈上,则会一并copy到堆上。 如果block没有...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,753
精华内容 8,301
关键字:

iosblock为什么用copy