Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone animateWithDuration中块完成内的递归调用?_Iphone_Animation_Uiview_Enumeration_Objective C Blocks - Fatal编程技术网

Iphone animateWithDuration中块完成内的递归调用?

Iphone animateWithDuration中块完成内的递归调用?,iphone,animation,uiview,enumeration,objective-c-blocks,Iphone,Animation,Uiview,Enumeration,Objective C Blocks,我有一套动画,需要按顺序操作,每一步都要进行各种检查。因为集合的大小是在运行时确定的,所以我希望使用递归调用。。。但我很难让它在“块”范式中运行 无论我是否使用 __block void (^myBlock)(BOOL) = ^(BOOL finished){ if (finished) [self nextStep];}; 或者不,如下面的代码片段所示。调试后,“self”变量似乎确实有效 NSEnumerator* stepEnumerator; -(void) mainRoutine

我有一套动画,需要按顺序操作,每一步都要进行各种检查。因为集合的大小是在运行时确定的,所以我希望使用递归调用。。。但我很难让它在“块”范式中运行

无论我是否使用

__block void (^myBlock)(BOOL) = ^(BOOL finished){ if (finished) [self nextStep];};
或者不,如下面的代码片段所示。调试后,“self”变量似乎确实有效

NSEnumerator* stepEnumerator;

-(void) mainRoutine {
    stepEnumerator = [myArray objectEnumerator];
    [self nextStep];
}

-(void) nextStep {
    id obj;
    if ((obj = [stepEnumerator nextObject])) {
        // Do my checking at each location
        ....

        // we have another spot to move to
        [UIView animateWithDuration:animationDuration
                         animations:^{self.frame = newFrame;}
                         completion:^(BOOL finished){ if (finished) [self nextStep];}];
        }
    }
    else {
        // we are done, finish house cleaning
    }
}
非常感谢您的帮助。
谢谢

我也不熟悉blocks,但我刚刚解决了一个类似的问题。在我的例子中,EXEC_BAD_访问是由于块超出范围而导致的。我怀疑在第二次递归中的某个时候,该块是用奇数堆栈帧创建的,因为它在另一个块内执行

我的解决方案是将区块保存在标记为副本的属性中,例如

@property (nonatomic,copy) BOOL (^callback)(DownloadProgress*);

这确保了在原始块对象超出范围并且是GC的情况下,所有内容都保留在副本中。

对提出的问题的回答是,是的,块完成中的递归调用是有效的。 @比尔布拉斯基提出了一个很好的观点,那就是街区失去了活动范围。我不知道是否需要这样做,因为我还没有发现这是我的情况的问题。在通过递归函数进行的每次连续迭代中,我似乎都能正常工作

我最初编写并提交的代码的核心问题是FastEnumerator的使用。当您离开当前函数并冒险进入堆栈帧的另一个事件循环/新部分时,这肯定会丢失。我意识到,当我进一步思考它时,可能有相当多的幕后工作要使FastEnumeration工作,而且离开该方法会破坏设置是非常合乎逻辑的

作为修复,我用一个简单的整数替换了nsemulator,然后每次通过递归函数递增该整数。我不太喜欢这个,因为它可能会导致出界风格的问题,而FastEnumerator不会,数组中的obj也不会,但我不知道还有其他解决方案。我想我会把它作为一个单独的问题发布

更正代码:

int index;

-(void) mainRoutine {
    index = 0;
    if (index < [myArray count]) {
        [self nextStep];
    }
}

-(void) nextStep {
    // obtain the object from the array
    id obj = [myArray objectAtIndex:index++];
    // do my checking on the object
    ...

    [UIView animationWithDuration:animationDuration
                       animations:^{self.frame = [view frame];}
                      completions:^(BOOL finished) {
                          if (finished && index < [myArray count]) {
                              [self nextStep];
                          }
                          else {
                              // We are done, clean up
                              ...
                          }
                      }];
}
再次感谢@BillBrasky,你帮我找到了解决这个问题的正确途径。我太专注于递归,我对“self”对象的快速分析看起来很好,因为除了一个项目外,其他一切都很好。再加上调试器断断续续地运行,而不是实际的违规行,谁知道我会盯着代码看多久而看不到真正的问题


干杯。

我认为您对情况的分析是正确的,堆栈帧不好,但保留块作为属性并不能解决我的问题。但它确实给了我一些想法,我开始深入挖掘。正如我前面提到的,“self”变量似乎在块内有效,所有用户可读的值都是实心的。但是,访问NSE分子似乎会导致崩溃。根据您的反馈,我尝试将其包装到属性中,但也没有解决。现在我想知道我是否完全误解了这个问题。再次感谢。进一步的调试表明这是正确的,NSEnumerator对象导致了问题。所有其他“self”ivar都是正确的,但在第一个动画完成后第一次调用块时,stepEnumerator是假的,尽管它被放置在属性中。