我正在尝试用IOS在IOS中编写一个完成处理程序,但我不确定它为什么不起作用。
这是我到目前为止所拥有的
typedef void(^myCompletion)(BOOL);
-(void) showAnswer {
[self showAnswer:^(BOOL finished) {
if (finished) {
LnbScene *scene = (LnbScene *)gameScene.lnbScene;
//once the tiles position have been updated then move to the next riddle
[scene nextRiddle];
}
}];
}
// This method should update the position of tiles on the scene
-(void) showAnswer:(myCompletion) compblock{
LnbScene *scene = (LnbScene *)gameScene.lnbScene;
NSArray *tilesArray = [scene.tilesBoundary children];
for (Tile *tile in tilesArray) {
if (tile.positionInAnswer != 17) {
[tile removeFromParent];
[scene.spacesBoundary addChild:tile];
CGPoint targetPoint = CGPointMake(tile.targetPoint.x, tile.targetPoint.y + 6);
tile.position = targetPoint;
}
}
compblock(YES);
}
我从一个场景调用showAnswer方法如下:
GameViewController *gVC = (GameViewController *)self.window.rootViewController;
[gVC showAnswer];
当我单步执行代码时,我没有遇到任何错误,并且序列按预期进行,即。更改磁贴位置,然后完成处理程序触发nextRiddle方法。唯一的问题是没有任何接口被更新。有什么我想念的吗?
我已经通过取出完成块测试了tile重新定位的代码,我在界面中查看它并获得所需的结果。所以我很确定问题在于我是如何实现这些块的。我以前从未写过一个块,所以我真的在黑暗中。
-(void) showAnswer {
LnbScene *scene = (LnbScene *)gameScene.lnbScene;
NSArray *tilesArray = [scene.tilesBoundary children];
for (Tile *tile in tilesArray) {
if (tile.positionInAnswer != 17) {
[tile removeFromParent];
[scene.spacesBoundary addChild:tile];
CGPoint targetPoint = CGPointMake(tile.targetPoint.x, tile.targetPoint.y + 6);
tile.position = targetPoint;
}
}
}
答案 0 :(得分:1)
我认为问题似乎是一个概念上的错误 - " flow"代码
在-(void) showAnswer:(myCompletion) comp block
方法中如实地表示了表示层中及时UI元素的流程。
然而在实践中并非如此直截了当。 UI层以60 Hz帧速率渲染。这意味着您每秒可以看到60个(帧)屏幕,并且每个屏幕的内容需要提前计算,处理,展平,渲染。
这意味着1帧(屏幕)周期/通过持续约。 16毫秒。如果我没记错的话,你作为程序员有11毫秒的时间来提供所有相关的代码,以便它可以被处理成视觉信息。这段代码经过一次性处理,这是我们问题的答案。
想象一下,如果你有一个方法可以说
{
//some other UI code...
self.view.backgroundColor = [UIColor greenColor];
self.view.backgroundColor = [UIColor yellowColor];
//some other UI code...
}
现在假设我们在1米这样的16毫秒传球。 在任何渲染发生之前,这段代码将被预先处理,并且结果背景颜色将是黄色。为什么?因为在循环准备阶段,处理此代码并且框架将绿色解释为无意义,因为该值立即被黄色覆盖。 因此,渲染器的说明将仅包含黄色背景信息。
现在回到你的实际代码。我认为你的所有代码都处理得足够快,以适应11毫秒的窗口,问题是你并没有真正等待瓦片的交换,因为有一个带有YES参数的块作为方法的一部分而且已经滑动无论下一步是什么。
所以渲染确实得到了简单地继续下一步的指示。它没有动画。
尝试将此"平铺交换"进入"动画"块
[UIview animateWithDuration:....完成]方法..并将您的块放入完成块。是的,你会在一个区块中有一个区块,但没关系。
[UIView animateWithDuration:0.4f
animations:^{
//tile swapping code
}
completion:^(BOOL finished)
{
complBlock(YES);
}];
我不完全确定它是否会起作用但是试试吧。
答案 1 :(得分:0)
UI关联方法应该调用主线程。你可以试试这个:
[self showAnswer:^(BOOL finished) {
if (finished) {
LnbScene *scene = (LnbScene *)gameScene.lnbScene;
dispatch_async(dispatch_get_main_queue(), ^{
[scene nextRiddle];
});
}
}];