簡體   English   中英

為什么重復創建和刪除SKShapeNode和SKNode會導致內存泄漏?

[英]Why does creating and removing SKShapeNode and SKNode repeatedly cause a memory leak?

使用Xcode附帶的sprite kit模板,我修改場景如下:

#import "MyScene.h"

@interface MyScene ()
@property (nonatomic,strong)SKNode *floor;
@end

@implementation MyScene

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */
    }
    return self;
}

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
    [self removeAllChildren];
    self.floor = nil;
    self.floor = [SKNode node];

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, nil, 0, 10);

    for(int i = 2; i<self.frame.size.width; i+=2)
    {
        CGPathAddLineToPoint(path, nil, i, 10);
    }

    self.floor.physicsBody = [SKPhysicsBody bodyWithEdgeChainFromPath:path];
    SKShapeNode *shape = [SKShapeNode node];
    shape.path = path;
    shape.strokeColor = [UIColor redColor];

    [self.floor addChild:shape];
    [self addChild:self.floor];

    CGPathRelease(path); 
}

@end

該應用程序似乎繼續使用更多內存,直到它掛起或崩潰(達到約180MB后)。 使用泄漏和分配工具,我發現了以下內容:

泄漏: Leaks窗口的屏幕截圖 分配: 分配窗口的屏幕截圖

從圖像中可以看出,存在大量使用內存的Malloc調用。 我不直接調用Malloc - 似乎這些調用是由SpriteKit完成的。 同樣,存在許多內存泄漏,這似乎也是由於SKShapeNode,SKNode或其他Sprite Kit對象造成的。

我如何解決或解決此內存(泄漏)問題? 我必須每幀創建SKShapeNodes和SKNodes。 這段代碼只是用來說明問題的一個例子 - 我的實際項目使用動態生成的路徑要復雜得多(不像本例中那樣是靜態的)。

這是精靈工具包中的一個錯誤。 問題不僅在於SKShapeNode,還在於SKPhysicsBody。

使用CGPath創建物理主體或形狀會導致內存泄漏。 您可以通過注釋物理主體或形狀以及運行具有泄漏,分配和內存監視器的儀器來驗證這一點。

即使您正確釋放路徑,sprite工具包也不在內部。 你什么都做不了!

啟動儀器,觀察內存增長! XD

編輯:這個錯誤出現在iOS 7.0中。 我是不是已經修復了7.1或更高版本,因為我因為這個bug而停止使用SpriteKit。 可以通過簡單測試來驗證它是否已修復。

我在閱讀另一篇文章時意識到了這個問題。 SKShapeNode弄亂了SKShapeNode ,確實驗證了這里指出的內存泄漏問題。

在這樣做的時候,我有了一個想法......

不是一個新想法,更多是一個改變用途的想法。 這個奇妙的想法實際上允許我使用SKShapeNodes到我心中的內容:)

POOLING

是的......我剛創建了一個SKShapeNodes池,我根據需要重用了它。 有什么區別讓:)

您只需在需要時重新定義路徑,使用返回游泳池完成后,它將等待您稍后再次玩游戲。

SKScene創建名為pool的ivar或屬性NSMutableArray ,並在初始化SKScene時創建它。 您可以在init期間使用形狀節點填充數組,也可以根據需要創建它們。

這是我為從池中獲取新節點而創建的快速方法:

-(SKShapeNode *)getShapeNode
{
    if (pool.count > 0)
    {
        SKShapeNode *shape = pool[0];
        [pool removeObject:shape];
        return shape;
    }

    // if there is not any nodes left in the pool, create a new one to return
    SKShapeNode *shape = [SKShapeNode node];

    return shape;
}

所以無論你在場景中需要SKShapeNode,你都會這樣做:

SKShapeNode *shape = [self getShapeNode];
// do whatever you need to do with the instance

完成使用shape節點后,只需將其返回到池並將路徑設置為。 例如 :

[pool addObject:shape];
[shape removeFromParent];
shape.path = NULL;

我知道這是一種解決方法,而不是一個理想的解決方案,但對於任何想要使用大量SKShapeNodes而不是流失內存的人來說,這肯定是一種非常可行的解決方法。

我正在使用iOS 7.1.1並遇到了同樣的問題。 但是,通過在從父項中刪除形狀之前將SKShapeNode的path屬性設置為nil確實可以解決此問題 - 不再有泄漏。

我有同樣的問題。

場景添加了一個復合節點(SKShape與SKSprite)然后我從場景中刪除了這個節點並再次添加(我泄漏了兩個節點)。

從場景中刪除后,我的泄漏用娛樂復合節點修復

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM