For循环冻结Obj-C

For Loop Freeze Obj-C

所以这个循环在skscene中运行。它在我的多人游戏中运行得很好,但是..在单人游戏模式下它运行得不太好..

问题是,它的意思是循环执行快速动画。然而,整个事情只是在循环结束时冻结和动画。

for (int i = 0; i < 7; i++) {
    //to loop between players
    for (int j = 0; j < 4; j++) {

        NSString *imageName = [NSString stringWithFormat:@"back"];
        NSString *bundle = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
        UIImage *image = [[UIImage alloc] initWithContentsOfFile:bundle];
        SKTexture *texture = [SKTexture textureWithImage:image];
        cardDisplay = [CardSpriteNode spriteNodeWithTexture:texture];
        cardDisplay.size = CGSizeMake(104, 144);
        cardDisplay.position = _dealPosition;
        cardDisplay.zPosition = zPosCount;
        zPosCount++;
        cardDisplay.userInteractionEnabled = YES;
        cardDisplay.name = @"cardBack";
        [self addChild:cardDisplay];


        CGPoint moveToPosition;
        //change position to deal to
        if (j == 0) {
            moveToPosition = position1;
        }
        else if (j == 1) {
            moveToPosition = position2;
        }
        else if (j == 2) {
            moveToPosition = position3;
        }
        else if (j == 3) {
            moveToPosition = position4;
        }

        [cardDisplay runAction:[SKAction moveTo:moveToPosition duration:0.3]];
        [cardDisplay runAction:[SKAction fadeOutWithDuration:0.4]];
        [NSThread sleepForTimeInterval:0.1];

        if (i == 6 && j == 4 - 1) {
            SKNode *node = [self childNodeWithName:@"cardBack"];
            [node removeAllChildren];

            for (int p = 0; p < [playerCards count]; p++) {

                addBegin = p * (cardDisplay.size.width / 3.0);
                NSString *imageName = [NSString stringWithFormat:@"%@", playerCards[p]];
                NSString *bundle = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
                UIImage *image = [[UIImage alloc] initWithContentsOfFile:bundle];
                SKTexture *texture = [SKTexture textureWithImage:image];
                cardDisplay = [CardSpriteNode spriteNodeWithTexture:texture];
                cardDisplay.size = CGSizeMake(104, 144);
                cardDisplay.anchorPoint = CGPointMake(0.5, 0.5);
                cardDisplay.position = CGPointMake(-self.frame.size.width/2.8 + addBegin, -300);
                cardDisplay.zPosition = 1;
                cardDisplay.userInteractionEnabled = NO;
                cardDisplay.name = [NSString stringWithFormat:@"%@", playerCards[p]];
                [self addChild:cardDisplay];

                CGPoint moveToNewPosition = CGPointMake(-self.frame.size.width/2.8 + addBegin, -218);

                [cardDisplay runAction:[SKAction moveTo:moveToNewPosition duration:1]];
                [NSThread sleepForTimeInterval:0.2];
            }
        }
    }
}

就像我说的,这在我的另一个 skscene 中工作正常,但在这个 skscene 中却不行,据我所知,一切都已初始化。

    [self performSelectorInBackground:@selector(dealCards) withObject:self];

不确定为什么,但它有效。

不要使用这个答案。

中央调度中心 (GCD)

来自 Apple 的文档:

Grand Central Dispatch (GCD) comprises language features, runtime libraries, and system enhancements that provide systemic, comprehensive improvements to the support for concurrent code execution on multicore hardware in iOS and OS X.

GCD 的使用非常简单。下面是使用 GCD 在单独的线程上执行代码的示例。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    for (int i = 0; i < 7; i++) {
        //to loop between players
        for (int j = 0; j < 4; j++) {
            
            NSString *imageName = [NSString stringWithFormat:@"back"];
            NSString *bundle = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
            UIImage *image = [[UIImage alloc] initWithContentsOfFile:bundle];
            SKTexture *texture = [SKTexture textureWithImage:image];
            cardDisplay = [CardSpriteNode spriteNodeWithTexture:texture];
            cardDisplay.size = CGSizeMake(104, 144);
            cardDisplay.position = _dealPosition;
            cardDisplay.zPosition = zPosCount;
            zPosCount++;
            cardDisplay.userInteractionEnabled = YES;
            cardDisplay.name = @"cardBack";
            dispatch_async(dispatch_get_main_queue(), ^(void){
                    [self addChild:cardDisplay];
            });
            
            CGPoint moveToPosition;
            //change position to deal to
            if (j == 0) {
                moveToPosition = position1;
            }
            else if (j == 1) {
                moveToPosition = position2;
            }
            else if (j == 2) {
                moveToPosition = position3;
            }
            else if (j == 3) {
                moveToPosition = position4;
            }
            
            [cardDisplay runAction:[SKAction moveTo:moveToPosition duration:0.3]];
            [cardDisplay runAction:[SKAction fadeOutWithDuration:0.4]];
            [NSThread sleepForTimeInterval:0.1];
            
            if (i == 6 && j == 4 - 1) {
                SKNode *node = [self childNodeWithName:@"cardBack"];
                [node removeAllChildren];
                
                for (int p = 0; p < [playerCards count]; p++) {
                    
                    addBegin = p * (cardDisplay.size.width / 3.0);
                    NSString *imageName = [NSString stringWithFormat:@"%@", playerCards[p]];
                    NSString *bundle = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
                    UIImage *image = [[UIImage alloc] initWithContentsOfFile:bundle];
                    SKTexture *texture = [SKTexture textureWithImage:image];
                    cardDisplay = [CardSpriteNode spriteNodeWithTexture:texture];
                    cardDisplay.size = CGSizeMake(104, 144);
                    cardDisplay.anchorPoint = CGPointMake(0.5, 0.5);
                    cardDisplay.position = CGPointMake(-self.frame.size.width/2.8 + addBegin, -300);
                    cardDisplay.zPosition = 1;
                    cardDisplay.userInteractionEnabled = NO;
                    cardDisplay.name = [NSString stringWithFormat:@"%@", playerCards[p]];
                    dispatch_async(dispatch_get_main_queue(), ^(void){
                        [self addChild:cardDisplay];
                    });
                    
                    CGPoint moveToNewPosition = CGPointMake(-self.frame.size.width/2.8 + addBegin, -218);
                    
                    [cardDisplay runAction:[SKAction moveTo:moveToNewPosition duration:1]];
                    [NSThread sleepForTimeInterval:0.2];
                }
            }
        }
    }
});

你会注意到我使用的一些地方:

dispatch_async(dispatch_get_main_queue(), ^(void){
    [self addChild:cardDisplay];
});

这将始终包含影响 UI 的代码;所有 UI 代码必须在主线程上执行。