iOS - __weak&&__block

本文详细介绍了在Objective-C中使用weak、strong和block时如何解决循环引用问题,包括如何通过声明strong变量、手动赋值nil以及使用__block修饰符来避免内存泄漏。

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

 __weak 本身是可以避免循环引用的问题的, 但是其会导致外部对象释放了之后, block 内部也访问不到这个对象的问题.

 我们可以通过在 block 内部声明一个 __strong 的变量来指向 weakObj, 使外部对象既能在 block 内部保持住, 又能避免循环引用的问题.

 __block 本身无法避免循环引用的问题, 但是我们可以通过在 block 内部手动把 blockObj 赋值为 nil 的方式来避免循环引用的问题. 

 另外一点就是 __block 修饰的变量在 block 内外都是唯一的, 要注意这个特性可能带来的隐患. 

#import <Foundation/Foundation.h>
#import "MyObject.h"
#define MLog(prefix, obj) {NSLog(@"变量内存地址:%p, 变量值:%p, 指向对象:%@, --> %@", &obj, obj, obj, prefix);}
void testWeak() {
    MyObject *obj = [[MyObject alloc] init];
        obj.text = @"11111111111";
        MLog(@"obj", obj);
    
        __weak MyObject *weakObj = obj;
        MLog(@"weakObj", weakObj);
        void (^testWeakBlock)() = ^() {
            MLog(@"weakObj - block", weakObj);
        };
        testWeakBlock();
        obj = nil;
        testWeakBlock();
}
void testWeak2() {
    MyObject *obj = [[MyObject alloc] init];
    obj.text = @"123456789";
    MLog(@"obj", obj);
    __weak MyObject *weakObj = obj;
    MLog(@"weakObj-0", weakObj);
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        __strong MyObject *strongObj = weakObj;
        sleep(4);
        MLog(@"weakObj-block", weakObj);
        MLog(@"strongObj-block", strongObj);
    });
    
    sleep(1);
    obj = nil;
    MLog(@"weakObj-1", weakObj);
    sleep(4);
    MLog(@"weakObj-2", weakObj);
    
    //sleep(10);
    
}
void testBlock() {
    MyObject *obj = [[MyObject alloc] init];
    obj.text = @"1111111111";
    MLog(@"obj", obj);
    __block MyObject *blockObj = obj;
    obj = nil;
    MLog(@"blockObj", blockObj);
    void(^testBlockBlock)() =^() {
        MLog(@"blockObj-block", blockObj);
        MyObject *obj2 = [[MyObject alloc] init];
        obj2.text = @"2222222222";
        MLog(@"obj2", obj2);
        blockObj = obj2;
        MLog(@"blockObj-block", blockObj);
    };
    NSLog(@"%@", testBlockBlock);
    MLog(@"blockObj-2", blockObj);
    testBlockBlock();
    MLog(@"blockObj - 3", blockObj);
}
void testBlock2() {
    MyObject *obj = [[MyObject alloc] init];
    obj.text = @"1111111111";
    MLog(@"obj", obj);
    __block MyObject *blockObj = obj;
    obj = nil;
    void (^testBlock2Block)() = ^() {
        MLog(@"blockObj", blockObj);
    };
    obj = nil;
    testBlock2Block();
    MLog(@"blockObj", blockObj);
}
void testBlock3() {
    MyObject *obj = [[MyObject alloc] init];
    obj.text = @"1111111111";
    MLog(@"obj", obj);
    __block MyObject *blockObj = obj;
    obj = nil;
    void (^testBlock3Block)() = ^() {
        MLog(@"blockObj-block", blockObj);
        blockObj = nil;
    };
    obj = nil;
    testBlock3Block();
    MLog(@"blockObj", blockObj);
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //testWeak2();
        testBlock3();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值