【问题标题】:Sprite Kit leaks don't make senseSprite Kit 泄漏没有意义
【发布时间】:2014-11-19 01:24:33
【问题描述】:

我一直在运行 Instruments 以了解为什么我的 SKScene 不会解除分配并获得没有任何意义的“泄漏”。其中一个“泄漏”发生在正确解除分配并指向这一点的场景中:

border.path = path;

作为导致泄漏的行,但下一行是:

CGPathRelease(path);
border.lineWidth = 1.0f;
border.strokeColor = [SKColor yellowColor];
[border setAlpha:0.0f];
[border runAction:[SKAction fadeAlphaTo:1.0f duration:0.2f]];
[self addChild:border];

所以你可以清楚地看到它已经发布了。我也得到了以下方法的“泄漏”:

-(void)explosionShake{
//[self testTargets];
NSArray *objectArray = [self children];
for (SKNode *node in objectArray) {
    [node runAction:[SKAction moveBy:CGVectorMake(0.0f, 10.0f) duration:.05] completion:^{
        [node runAction:[SKAction moveBy:CGVectorMake(0.0f, -15.0f) duration:.05] completion:^{
            [node runAction:[SKAction moveBy:CGVectorMake(0.0f, 5.0f) duration:.05]];
        }];
         }];
    }

}

场景结束后,以及我从其父对象中删除的另一个对象。

这些“泄漏”是否是由于尝试在已从其父节点中删除的节点上运行操作而引起的?因为当“explosionshake”正在运行时,其中一个节点可能会以另一种方法从它的父节点中删除。这个方法怎么样:

SKEmitterNode *testForExplosion = [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:@"explosionTest" ofType:@"sks"]];
//testForExplosion.position = location;
//[testForExplosion setParticleSpeed:self.frame.size.width/self.gameSpeed];
SKNode *node = [SKNode node];
[self addChild:node];
[node setPosition:location];
[node runAction:[SKAction moveBy:CGVectorMake(-self.frame.size.width, 0) duration:self.gameSpeed]];
[node addChild:testForExplosion];
SKAction *wait = [SKAction waitForDuration:4.0f];
SKAction *remove = [SKAction removeFromParent];
NSArray *array = [NSArray arrayWithObjects:wait,remove, nil];
SKAction *sequence = [SKAction sequence:array];

方法中的第一行以红色突出显示,最后一行以绿色突出显示(这只是方法的一部分)。我很困惑为什么这些是“泄漏”,但这可能是导致我的场景没有被释放的原因。

如果有人能告诉我为什么这些方法可能导致内存泄漏,那将非常非常有帮助。当我的代码清楚地调用removeFromParent

【问题讨论】:

  • 如果您还没有在 xcode 中进行分析构建。 Instruments 和 Analyze 都可能出现误报。由于每个完成块都强烈引用节点,因此爆炸摇动可能会泄漏节点,但不能保证每个完成块都运行(可以随时停止操作)。为节点创建一个弱临时变量将解决这个问题,如果它确实是一个问题。这条路径很可能是误报,以前见过。
  • @LearnCocos2D 我已经进行了分析构建,只提出了一个“可能的泄漏”,我已修复。我觉得所有其他泄漏都是误报实在太好了,因为“泄漏”仪器页面总共显示了 33 个泄漏(尽管在对我的代码进行了一些修改之后,似乎没有一个泄漏链接到任何我的代码,这很奇怪),我的游戏场景没有解除分配,这让我觉得场景中一定存在某种问题。会不会是我的 iPhone 运行的是 iOS 7.1.2?
  • @LearnCocos2D 另外,您能否提供一个示例,说明如何创建对node 的“弱引用”?在我看过的所有教程中,我从来没有看到过关于这个的东西。

标签: memory-leaks sprite-kit


【解决方案1】:

1)
SKShapeNode 不是游戏中最可靠的职业。我的意思是,最好使用带有形状图像的SKSpriteNode。如果仍然使用SKShapeNode,请尝试以下代码。可能不行,但试试看。

- (void)dealloc
{
    if(self.shapeNode){
        [self.shapeNode setPath:NULL];
        [self.shapeNode removeFromParent];
        self.shapeNode = nil;
    }
}

2)
很明显,有一个对节点的强引用。可以重写如下:

-(void)explosionShake
{
    NSArray *objectArray = [self children];
    for (SKNode *node in objectArray) {

        // create a weak reference of the node
        __weak typeof(node) weaknode = node;

        // run action
        [node runAction:[SKAction moveBy:CGVectorMake(0.0f, 10.0f) duration:.05] completion:^{
            [weaknode runAction:[SKAction moveBy:CGVectorMake(0.0f, -15.0f) duration:.05] completion:^{
                [weaknode runAction:[SKAction moveBy:CGVectorMake(0.0f, 5.0f) duration:.05]];
            }];
        }];
    }
}

3)
第三部分似乎缺少一些代码,因为我没有看到泄漏。

查看其他线程以获取有关如何使用完成块运行操作的示例。 SKAction Perform Selector syntax error
希望这会有所帮助。

【讨论】:

  • 感谢您的评论,我只想澄清两点:1,sequence 执行的操作不会导致泄漏,但completion 会阻止?另外,在您的回答中,您的意思是在node 上运行第一个动作,然后在weaknode 上运行所有后续动作,而不是在weaknode 上运行所有3 个动作?为什么?
  • !) 当使用SKAction 序列时,您不会创建对对象的单独引用。你让 Sprite Kit 管理它。当使用完成块或SKActionrunBlock 并调用节点时,该块将创建对该节点的强引用。当节点从父节点中删除时,块将节点保留在内存中。 2) 没关系,你可以使用weaknode
  • 如果在 self 上运行一个操作,例如 [self runAction:action completion:^(void){block}],这会不会很重要?我需要使用“自我”的“弱”版本吗?
  • 没有。重要的是在块内。如果在块内使用self,则可能有泄漏。
  • 那么,我在块内引用的任何对象都必须是弱的吗?例如,在我的代码中,我有[weakSelf runAction:[SKAction waitForDuration:.5f] completion:^{ [self showTargetAtPositionIndex:2]; }];,我还必须将块内的self 变成weakSelf ?
猜你喜欢
  • 2014-04-14
  • 2014-05-16
  • 1970-01-01
  • 2019-12-20
  • 1970-01-01
  • 1970-01-01
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多