You aren't actually allocating a block in that code. The body of the block is all static content; nothing changes post compilation.
If you do this:
_weakBlock = ^void{
NSLog(@"Execution inside a weakBlock");
};
NSLog(@"%@", [_weakBlock class]);
You'll see this:
2018-10-21 09:33:48.827423-0500 kdkdkdkds[9367:1777827] __NSGlobalBlock__
The compiler recognized the block doesn't capture anything that might change at runtime and, accordingly, created a global static block which will never be allocated.
As @Brandon said in a comment, if you declared a local variable in your scope and caused a stack block to be allocated, that wouldn't go away until the end of the scope.
@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
Now, instance variable assignment changes the rules slightly because you are assigning out of scope.
@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
Wait. What? If that value is really being assigned to the ivar, then this is a ticking time bomb. So, let's try something:
If we add:
- (void)squarePants
{
NSLog(@"C; %@", [_weakBlock class]);
NSLog(@"P; %p", _weakBlock);
}
And then call it:
SpongeBob *bob = [[SpongeBob alloc] init];
[bob squarePants];
It crashes, as expected, because the stack block is no longer valid as init
's scope
(This seems rather mean. Then again, if you eliminate the warning, the crash goes away.)
Now, if you copy the block on assignment, then the immediate deallocation on assignment does kick in:
_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