block_copy何时使用

时间:2013-03-03 09:38:25

标签: ios objective-c objective-c-blocks

何时复制一个块?该文档说,当执行从定义它们的作用域返回时,块被“删除”。这意味着你不能直接从函数返回它们。如果只能在它们的定义范围仍然在调用堆栈上时使用块,他们不会像他们实际上那样有用“

所以,这是我尝试的代码,希望在viewDidLoad中完成执行后删除该块。

MyReaderController.h

@interface MyReaderController : UIViewController
{
    myBlockVar aBlockVar;
}
-(myBlockVar) getABlock;
@end

MyReaderController.m

@implementation MyReaderController
- (void)viewDidLoad
{
    [super viewDidLoad];
    aBlockVar=[self getABlock];
    NSLog(@"Block Result = %f",aBlockVar(1));
}
-(void) viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
    NSLog(@"Block Exists even after the execution completes=%@ %f",aBlockVar,aBlockVar(5));
}

-(myBlockVar) getABlock{
    return ^(int var){return 4.0f;};
}

@end

那么,这段代码是否需要将viewDidLoad更改为如下所示,如果不是,那么何时应该使用它。

- (void) viewDidLoad{
    [super viewDidLoad];
    aBlockVar=Block_copy([self getABlock]);
    NSLog(@"Block Result = %f",aBlockVar(1));
}

第2部分

后来我尝试使用以下代码,希望现在它将aBlockVar作为nil obj返回 viewDidDisappear。

- (void)viewDidLoad
{
    [super viewDidLoad];
    Blocker *blocker=[[Blocker alloc] init];
    myBlockVar myVar=[blocker getABlock];
    aBlockVar=myVar;
    NSLog(@"Block Result = %f",aBlockVar(1));
    blocker=nil;
    myVar=nil;
}

Blocker.m

#import "Blocker.h"

@implementation Blocker

-(myBlockVar) getABlock{
    return ^(int var){return 4.0f;};
}
@end

4 个答案:

答案 0 :(得分:5)

你在使用ARC吗?如果是这样,您无需使用Block_copyBlock_release

如果您是,那么您对修改后的代码是正确的,因为Block_copy将其从堆栈中取出并进入堆中,其有效保留计数为1.您还需要调用{{ 1}}在适当的情况下,当最终完成块时,为了使其平衡复制,有效地将保留计数恢复为0.

答案 1 :(得分:2)

使用@property (nonatomic, copy) (int)(^myBlock)(void);

让系统为您做好所有内存管理!

初​​始化:

self.myBlock = ^int(void){
    return 4.0;
};

如果你想在self.myBlock = NULL;

的某个地方销毁你的区块

答案 2 :(得分:2)

现有答案的补遗:

即使您正在使用ARC,在某些情况下您仍然需要Block_copy。 例如,从NSInvocation中提取块参数并在函数返回后使用它。

- (void)interceptInvocation:(NSInvocation *)call {
    BlockType block;
    [call getArgument:&block atIndex:2];  // ARC cannot see this happen
    block = (__bridge BlockType)Block_copy((__bridge void *)block);

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        block();
    });
}

如果没有副本,该块将在运行时被释放。 似乎没有必要匹配Block_release,因为当我添加了一个因崩溃太多而崩溃的时候。

答案 3 :(得分:1)

,电弧永不,没有弧:


:当你有一个STACK块并希望将它保存为HEAP块时(例如,当你在一个函数中有一个块并希望它在你退出函数后生存时!)

然后你需要阻止它。


你也需要像保存NSString那样保留/释放它(使用block_copy / block_release)