iOS底层学习-day-9

前言-OC语法篇

我是一名iOS开发者, iOS底层 菜鸟的进阶之路30天。

问题

block的属性修饰词为什么是copy?使用block有哪些使用注意?

  • block一旦没有进行copy操作,就不会在堆上
  • 使用注意:循环引用问题

block在修改NSMutableArray,需不需要添加__block?

  • 不需要。修改内容也是对数组的使用,只有对对象赋值的时候才需要__block。

block的持有问题

		//栈空间的block是不可以对对象强引用的,堆空间的block是可以持有对象
        Block block;
        {
            Person *person = [[Person alloc] init];
            person.age = 10;
            
            block = ^{
                NSLog(@"---------%d", person.age);
            };
        }
        
        NSLog(@"------");

		Block block;
        {
            Person *person = [[Person alloc] init];
            person.age = 10;
            //如果是这样就,这个block就只是栈上的,就不会对外部变量进行强引用(ARC环境)
            ^{
                NSLog(@"---------%d", person.age);
            };
        }
        
        NSLog(@"------");
  • 当block内部访问了对象类型的auto变量时

    • 如果block是在栈上,将不会对auto变量产生强引用
  • 如果block被拷贝到堆上

    • 会调用block内部的copy函数
    • copy函数内部会调用_Block_object_assign函数
    • _Block_object_assign函数会根据auto变量的修饰符(__strong、__weak__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用
  • 如果block从堆上移除

    • 会调用block内部的dispose函数
    • dispose函数内部会调用_Block_object_dispose函数
      _Block_object_dispose函数会自动释放引用的auto变量(release)

p的强引用什么时候被释放问题

  • 全局变量没有捕获,因为全局变量直接可以访问
  • 这样会,先强引用里面的代码,所以,weakP 1秒也是之后被释放,p 3秒之后被释放
	Person *p = [[Person alloc] init];
    
    __weak Person *weakP = p;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1-------%@", weakP);
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-------%@", p);
        });
    });
  • p 1秒之后被释放,weakP 一下就被释放
	Person *p = [[Person alloc] init];
    
    __weak Person *weakP = p;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1-------%@", p);
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-------%@", weakP);
        });
    });

在block中修改变量

  • 不可以修改,因为在block里相当于拿到block的行参
int age = 10;
Block block1 = ^{
	age = 30;
	NSLog(@"age is %d", age);
};
  • 这样就可以改了,因为是直接改指针指向的内存,全局变量也可以改
static int age = 10//会永久在内存中
Block block2 = ^{
	age = 30;
	NSLog(@"age is %d", age);
};
  • 编译器会将__block变量包装成一个对象
//__blcok只能修改auto变量
//还是一个auto变量
__block int age = 10;

Block block3 = ^{
	age = 20;
	NSLog(@"age is %d", age);
};
  • __block本质
    在这里插入图片描述
发布了12 篇原创文章 · 获赞 0 · 访问量 112

猜你喜欢

转载自blog.csdn.net/weixin_41732253/article/details/103945847