gpt4 book ai didi

ios - Objective-C 创建弱 block 来检查内存释放

转载 作者:行者123 更新时间:2023-11-28 18:14:58 24 4
gpt4 key购买 nike

我读到如果你将一个新对象分配给弱属性,该对象将在分配后释放。甚至来自编译器的警告也是一样的。

@interface RetainCycleObjCViewController ()
{
}
@property (nonatomic, weak) void (^weakBlock)(void);
@end

@implementation RetainCycleObjCViewController
- (void)viewDidLoad {
[super viewDidLoad];

_weakBlock = ^void{
NSLog(@"Execution inside a weakBlock");
};

_weakBlock();
}
@end

对于 weakBlock,我得到了相同的警告:Assigning block literal to a weak variable;分配后对象将被释放

但是当我在下一行执行 _weakBlock() 时,它仍然打印语句。这怎么可能?因为给定 0 引用计数,新创建的 block 对象现在应该已经从内存中删除了吗?

最佳答案

您实际上并没有在该代码中分配 block 。 block 的主体都是静态内容;编译后没有任何变化。

如果你这样做:

    _weakBlock = ^void{
NSLog(@"Execution inside a weakBlock");
};
NSLog(@"%@", [_weakBlock class]);

你会看到这个:

2018-10-21 09:33:48.827423-0500 kdkdkdkds[9367:1777827] __NSGlobalBlock__

编译器识别出该 block 不会捕获任何可能在运行时更改的内容,因此创建了一个永远不会分配的全局静态 block 。

正如@Brandon 在评论中所说,如果您在范围内声明了一个局部变量并导致分配了一个堆栈 block ,那么直到范围结束时它才会消失。

@autoreleasepool {
void __weak (^_weakBlock)(void);
int k = 2;
_weakBlock = ^void{
NSLog(@"Execution inside a weakBlock (%d)", k);
};
NSLog(@"C; %@", [_weakBlock class]);
NSLog(@"P; %p", _weakBlock);
}
2018-10-21 09:36:31.585458-0500 kdkdkdkds[9392:1780803] C; __NSStackBlock__
2018-10-21 09:36:31.586291-0500 kdkdkdkds[9392:1780803] P; 0x7ffeefbff4c0

现在,实例变量赋值稍微改变了规则,因为您在范围外赋值。

@interface SpongeBob:NSObject
@end

@interface SpongeBob ()
{
}
@property (nonatomic, weak) void (^weakBlock)(void);
@end

@implementation SpongeBob
- (instancetype)init
{
self = [super init];
if (self) {
int k = 2;
_weakBlock = ^void{
NSLog(@"Execution inside a weakBlock (%d)", k);
};
NSLog(@"C; %@", [_weakBlock class]);
NSLog(@"P; %p", _weakBlock);
}
return self;
}
@end


int main(int argc, const char * argv[]) {
@autoreleasepool {
[[SpongeBob alloc] init];
}
return 0;
}

2018-10-21 09:43:39.518545-0500 kdkdkdkds[9480:1787889] C; __NSStackBlock__
2018-10-21 09:43:39.518883-0500 kdkdkdkds[9480:1787889] P; 0x7ffeefbff488

等等。什么?如果该值真的被分配给了 ivar,那么这就是一颗定时炸弹。那么,让我们尝试一下:

如果我们添加:

- (void)squarePants
{
NSLog(@"C; %@", [_weakBlock class]);
NSLog(@"P; %p", _weakBlock);
}

然后调用它:

    SpongeBob *bob = [[SpongeBob alloc] init];
[bob squarePants];

正如预期的那样,它崩溃了,因为堆栈 block 不再有效作为 init 的范围

(这似乎很刻薄。再一次,如果你消除警告,崩溃就会消失。)

现在,如果您在赋值时复制 block ,那么赋值时的立即释放开始:

    _weakBlock = [^void{
NSLog(@"Execution inside a weakBlock (%d)", k);
} copy];

2018-10-21 09:48:04.295762-0500 kdkdkdkds[9510:1792549] C; (null)
2018-10-21 09:48:04.296167-0500 kdkdkdkds[9510:1792549] P; 0x0

关于ios - Objective-C 创建弱 block 来检查内存释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52913397/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com