2013-11-29 1 views
6

Используя шаблон набора спрайтов, который поставляется с Xcode, я изменить сцену, чтобы быть следующим:Почему создание и удаление SKShapeNode и SKNode неоднократно вызывают утечку памяти?

#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 

приложение, кажется, продолжать использовать больше памяти, пока она либо зависает, либо вылетает (после достижения около 180 Мб). Использование утечек и распределения инструментов, я нашел следующий:

Утечки: Screenshot of Leaks window Отчисления: Screenshot of Allocations window

Как видно из изображений, существует большое количество таНоса вызовов с использованием памяти. Я не называю Malloc напрямую - кажется, эти вызовы сделаны SpriteKit. Аналогичным образом, существует ряд утечек памяти, которые также, по-видимому, связаны с SKShapeNode, SKNode или другими объектами Sprite Kit.

Как мне решить проблему или решить эту проблему? Мне нужно создать SKShapeNodes и SKNodes каждый кадр. Этот код является просто образцом для иллюстрации проблемы - мой фактический проект намного сложнее с динамически создаваемыми путями (не статичными, как в этом примере).

+0

CFPathRelease означает, что вы не используете ARC, правильно? – LearnCocos2D

+0

Нет. Я использую ARC. - Это проект Sprite Kit. –

+0

CGMutablePathRef использует C API, поэтому вы несете ответственность за его выпуск. Если вы не вызываете CGMutablePathRelease, вы будете утечка памяти, и «Анализ» предупредит вас. –

ответ

12

Это ошибка в комплекте спрайтов. Проблема заключается не только в SKShapeNode, но и в SKPhysicsBody.

Создание физического тела или формы с использованием CGPath вызывает утечку памяти. Вы можете проверить это, отметив либо физическое тело, либо форму, и работающие приборы с утечками, выделениями и монитором памяти.

Даже если вы правильно отпустите путь, комплект спрайтов не будет внутренне. Вы ничего не можете сделать!

Приступайте к работе с инструментами и наблюдайте за ростом памяти! XD

EDIT: эта ошибка присутствовала в iOS 7.0. Было ли это исправлено в 7.1 или новее, мне неизвестно, поскольку я прекратил использовать SpriteKit из-за этой ошибки. Можно проверить, исправлено ли это путем простого тестирования.

2

Мне стало известно об этой проблеме при чтении другого сообщения. Я немного испортил SKShapeNode и действительно проверил проблему утечки памяти, определенную здесь.

Делая это, у меня была идея ...

Не совсем новая идея, больше адаптированного один. Это прекрасная идея на самом деле позволило мне использовать SKShapeNodes к моему содержанию сердец :)

пулинговой

Да ... Я только что создал пул SKShapeNodes, что я повторно использовать по мере необходимости. Какая разница, которая делает :)

Вы просто переопределяете путь, когда это необходимо, когда это делается с помощью возврата в ваш пул, и он будет ждать вас, чтобы вы снова играли с ним позже.

Создайте ivar или свойство NSMutableArray в своем SKScene названии пула и создайте его, когда вы запустите 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 

Когда вы делаете это с помощью узла формы, просто возвращаете его в пул и задаете путь. Например:

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

Я знаю, что это временное решение, а не идеальное решение, но, конечно, это очень жизнеспособный обходной путь для тех, кто хочет использовать большое количество SKShapeNodes и не кровоточат памяти.

2

Я использую iOS 7.1.1 и имел ту же проблему. Однако, установив свойство пути SKShapeNode равным nil, прежде чем удалять фигуру из родителя, устранить эту проблему - больше никаких утечек.

+0

u сохранил мои волосы – zinne

0

У меня та же проблема.

Сцена добавила один составной узел (SKShape с SKSprite), после чего я удалил этот узел из сцены и снова добавил (у меня были утечки двух узлов).

Моя утечка фиксируется рекреация соединения узла после удаления от сцены

 Смежные вопросы

  • Нет связанных вопросов^_^