[英]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后)。 使用泄漏和分配工具,我發現了以下內容:
泄漏: 分配:
從圖像中可以看出,存在大量使用內存的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.