首页 文章

完成块目标-C

提问于
浏览
0

我正在尝试用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;
        }
    }
}

2 回答

  • 0

    我认为问题似乎是一个概念上的错误 - -(void) showAnswer:(myCompletion) comp block 方法中的"flow"代码在表示层中如实地表示 the flow of UI elements in time .

    然而在实践中并不是那么简单 . UI层以60 Hz帧速率渲染 . 这意味着您每秒可以看到60个(帧)屏幕,并且每个屏幕的内容需要提前计算,处理,展平,渲染 .

    这意味着1帧(屏幕)周期/通过持续约 . 16毫秒 . 如果我没记错的话,你作为程序员有11毫秒的时间来提供所有相关的代码,以便它可以被处理成视觉信息 . 这块代码被处理 all at once ,这是 answer to our problem .

    想象一下,如果你有一个可以说的方法

    {
       //some other UI code...
       self.view.backgroundColor = [UIColor greenColor]; 
       self.view.backgroundColor = [UIColor yellowColor]; 
       //some other UI code...
    }
    

    现在假设我们在1个这样的16毫秒传球中 . 在任何渲染发生之前,这段代码将被预先处理,并且结果背景颜色将是黄色 . 为什么?因为在循环准备阶段,处理此代码并且框架将绿色解释为无意义,因为该值立即被黄色覆盖 . 因此,渲染器的指令将仅包含黄色背景信息 .

    现在回到你的实际代码 . 我认为所有代码的处理速度都足够快,以适应11毫秒的窗口,问题是你并不真的等待瓦片的交换,因为有一个带有YES参数的块作为方法的一部分而且已经滑动接下来的事情 .

    所以渲染确实得到了简单地继续下一步的指示 . 它没有动画 .

    尝试将"tile swapping"放入"animation"块
    [UIview animateWithDuration:....完成]方法..并将您的块放入完成块 . 是的,你会在一个区块中有一个区块,但没关系 .

    [UIView animateWithDuration:0.4f
                     animations:^{
                                     //tile swapping code
                                }
                     completion:^(BOOL finished)
                                 {
                                     complBlock(YES);
                                 }];
    

    我不完全确定它是否会起作用但让我们尝试一下 .

  • 1

    UI关联方法应该调用主线程 . 你可以试试这个:

    [self showAnswer:^(BOOL finished) {
       if (finished) {
         LnbScene *scene = (LnbScene *)gameScene.lnbScene;
    
         dispatch_async(dispatch_get_main_queue(), ^{
              [scene nextRiddle];
         });
       }
    }];
    

相关问题