__weak与__block的使用

本文介绍了__weak和__block在解决循环引用和修改外部变量中的作用。通过案例分析,展示了如何使用__weak避免block引起的循环引用,以及__block修饰变量以实现Block内外的可读可写。同时强调了__weak只能修饰对象,__block适用于对象和基本数据类型,且__block不会导致对象被释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、缘由

有时候会因为循环引用导致对象无法释放时,会导致内存泄漏问题,使程序内存无法及时释放而内存增加。有时候我们想在block块中修改外部变量或者对象的值或属性,这些问题和需求使我们不得不去想办法更好地解决,这个时候我们会想到的是使用__weak和__block进行修饰。

二、block定义

在进行__weak和__block使用之前,我们先来对block块的基本定义回味一下,让接下来阅读起来更加地流畅。

定义如下:void(^myBlock)(void)   返回类型(^myBlock)(参数类型)

也可以使用typedef来给复杂的Block定义别名,写法为:typedef void(^myBlock)(void);

三、?

    __weak typeof(self) weakSelf = self; // MRC下对象同样不会被释放
    self.block = ^{
        NSLog(@"%@", NSStringFromClass([weakSelf class]));
    };
    self.block();

案例一:__weak避免循环引用。当我们使用block块的时候,很容易就导致循环引用,可以使用__weak定义一个弱引用weakSelf,由于弱引用不持有对象实例,当对象不被使用时,weakSelf将会释放并被系统所回收,使得block块不再强引用着self不释放,避免出现循环引用。

    __block int num = 10; // __block可以修饰对象与基本数据类型
    //    __weak int num = 10; // __weak只能修饰对象,不能修饰基本数据类型
    self.block = ^{
        num++;
        NSLog(@"内部值:%d", num);
    };
    
    self.block();
    NSLog(@"外部值:%d", num);

案例二:使用__block修饰基本变量类型。当没有使用__block修饰变量num时,此时的num变量则可读不可写,因为此时Block块内部会将变量做处理,重新生成一个变量指向num,使得在Block块内外操作其实不是相同的num变量。当使用了__block变量时,Block块内部将使用此变量,不再生成新的变量,所以此时外部对变量num的操作也会改变Block块num变量的值。

//JZPerson.h
    @property (copy, nonatomic) NSString* name;

//ViewController.m 实现
    JZPerson* person = [[JZPerson alloc]init];
    person.name = @"mjz";
    
    __weak JZPerson* weakPerson = person;
    
    NSLog(@"地址:%p---%p", person, &person);
    NSLog(@"地址:%p---%p", weakPerson, &weakPerson);
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        
        __strong JZPerson* strongPerson = weakPerson;
        weakPerson.name = @"tsy";
        
        NSLog(@"person:  %@", person.name);
        NSLog(@"weakPerson:  %@", weakPerson.name);
        NSLog(@"strongPerson1: %@", strongPerson.name);
        
        sleep(3);
        
        NSLog(@"%@", weakPerson.name);
        NSLog(@"strongPerson2: %@", strongPerson.name);
        
    });
    
    NSLog(@"%@", weakPerson.name);
    person = nil;
    
    sleep(5);
    NSLog(@"end:  %@", weakPerson.name);

案例三:使用__strong强引用着__weak。__strong使得在使用对象期间,防止对象被释放后导致程序出错。在使用期间强引用着对象,__strong对象使用完毕后会被系统回收,成功地防止了对象在外部被不小心释放导致地问题。

 

总结:

__strong与__weak起到修饰符的作用,类似于属性关键字,强引用与弱引用;

__block可以修饰对象和基本数据类型;

__weak只能修饰对象,不能修饰基本数据类型;

__weak直接修饰生成对象会被释放,__block则不会。

 

参考阅读:

1.  __block与__weak

2.  《Objective-C高级编程 iOS与OS X多线程和内存管理》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值