Iphone 目标-C将块传递到块中

Iphone 目标-C将块传递到块中,iphone,retain,block,Iphone,Retain,Block,这是一个有点棘手的场景。我一直在研究块并第一次开始实现它们,我发现自己想要创建一个“复合块”。这是我的代码,大致如下: - (void)moveToPosition:(NSInteger)pos withVelocity:(CGFloat)vel onCompletion:(void(^)(BOOL completed))completionBlock { void (^compoundBlock) (BOOL completed) = ^(BOOL completed) {

这是一个有点棘手的场景。我一直在研究块并第一次开始实现它们,我发现自己想要创建一个“复合块”。这是我的代码,大致如下:

- (void)moveToPosition:(NSInteger)pos withVelocity:(CGFloat)vel onCompletion:(void(^)(BOOL completed))completionBlock
{

    void (^compoundBlock) (BOOL completed) = ^(BOOL completed) {
        [self unlockInteractionFromPullDownMenuTab];
        void(^innerCompletionBlock)(BOOL completed) = completionBlock;
        innerCompletionBlock(completed);
    };

    // Animate
    [UIView animateWithDuration: duration
                     animations: ^void{ [self.pullDownMenu setFrame:newFrame]; }
                     completion: compoundBlock
     ];


}
目标是获取传递到此方法中的代码块,向其添加一些内容,然后将其传递到动画方法调用中。但是,我在线路上的访问权限不好:

innerCompletionBlock(completed);
我认为我的innerCompletionBlock正在被释放,但我不完全确定原因。据我所知,块复制了你扔给它们的所有东西,包括对self的引用——它可以创建保留循环,而我最近学会了避免这种循环

实际上,我最初试过这个:

void (^compoundBlock) (BOOL completed) = ^(BOOL completed) {
    [self unlockInteractionFromPullDownMenuTab];
    completionBlock(completed);
};
但是我得到的是错误的访问,我认为可能compoundBlock没有复制completionBlock,所以我在块内显式声明了一个(block)变量,并分配给它,试图让它保留(可能有点傻,但我在ARC下运行,所以我无法进行手动保留调用)

无论如何,很明显,当compoundBlock传递到UIView时,它会被保留,但我不确定如何在compoundBlock中保留onCompletion/innerCompletionBlock,因为我在ARC下运行


提前感谢:)

在堆栈上创建块。您需要将
completionBlock
复制到堆中,以便在尝试运行它时确保它仍然有效。只需将此放在方法的顶部:

completionBlock = [completionBlock copy];

请注意,如果堆上已经存在
completionBlock
,则只返回相同的堆副本。

Aha,解决它。真的有点愚蠢

我多次调用方法
-(void)moveToPosition:…
并将
nil
传递给
completionBlock
参数…因为我在动画结束时不需要做任何额外的事情,只需要
[self-unlockInteractionFromPullDownMenuTab]是在复合块中附加的

有道理,对吧

…只有在调用块之前检查是否为零。如前所述,“当您执行一个块时,首先测试该块是否为nil很重要”。嗯,我在那里学到了教训

此代码适用于:

// Compound completion block
void (^compoundBlock) (BOOL completed) = ^(BOOL completed) {
    [self unlockInteractionFromPullDownMenuTab];
    if (completionBlock != nil) {
        completionBlock(completed);
    }
};

嗯…谢谢你的快速回答。我有一个问题:在ARC下是否仍然需要复制块?(似乎不是。)为了论证,如果我上面的示例中的两个块没有在ARC下运行,我将如何准确地调用copy?只需在方法顶部的
completionBlock
上复制一次,但不要复制到
compoundBlock
,因为UIView动画调用会在内部复制它本身?谢谢。如果不在ARC下,则每个
副本
必须通过
释放
自动释放
进行平衡。在许多情况下,没有必要在ARC下复制一个块,但仍有一些情况是必要的,所以我倾向于预防性地复制。这是不正确的。他不需要在MRC或ARC中显式复制示例中的块
completionBlock
。该方法不存储
completionBlock
,以供以后在任何地方使用,除非被另一个块
compoundBlock
捕获。当(如果)
compoundBlock
被复制时,它将自动复制
completionBlock