SKShapeNode и CGPathRef EXC_BAD_ACCESS

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

У меня есть функция, которая возвращает CGPathRef, который является указателем C на структуру.

-(CGPathRef)newPath
{
    CGMutablePathRef mutablePath = CGPathCreateMutable();
    //inserting quad curves, etc
    return mutablePath;
} 

Затем я передаю эти CGPathRefs, заворачивая их в UIBezierPath.

-(NSArray*)otherFunction
{
    CGPathRef ref = [self newPath];
    UIBezierPath *path = [UIBezierPath bezierPathWithCGPath: ref];
    NSArray* paths = @[path];
    CGPathRelease(ref);
    return paths;
}

Затем я беру возвращенный массив путей и отображаю их на экране с помощью SKShapeNode.

SKShapeNode *node = [SKShapeNode new];

NSArray* paths = [self otherFunction];
CGPathRef ref = [[paths firstObject] CGPath];

node.path = ref; 
node.fillColor = [UIColor orangeColor];
node.lineWidth = 2;

И наконец.

[self addChild:node];
CGPathRelease(node.path);

После того, как я повторяю эту последовательность действий несколько раз, моя программа ломается и показывает мне.

UIApplicationMain с кодом EXC_BAD_ACCESS = 2.

Я так понимаю утечка памяти.

Мой вопрос в том, как мне справиться с выпуском CGPathRef, когда я в конечном итоге передаю его через несколько функций и обертываю его в другом классе?

Я обновил код и теперь получаю ошибку EXC_I386_GPFLT.


person i2Fluffy    schedule 11.01.2016    source источник
comment
Я предлагаю вам опубликовать фактический код, который компилируется, а не путь из развернутой функции otherFunction.   -  person 0x141E    schedule 11.01.2016


Ответы (2)


Я вижу три проблемы.

  1. Я не очень хорошо знаком с SKShapeNode, но из документации похоже, что он просто использует указанный вами путь, не копируя его (в отличие от UIBezierPath). В этом случае вам нужно скопировать путь из UIBezierPath в CGPathRef, потому что в противном случае он будет освобожден после освобождения UIBezierPath. Например:

    SKShapeNode *node = [SKShapeNode new];
    CGPathRef pathCopy = CGPathCreateCopy(/* path from other function unwrapped */);
    node.path = pathCopy;
    ...
    

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

    CGPathRelease(node.path);
    
  2. Похоже, у вас есть некоторые утечки памяти в опубликованном вами коде: вы создаете CGPathRef в newPath, копируете их в UIBezierPath в otherFunction и никогда их не удаляете. Это не вызовет вашей проблемы, но может вызвать других в будущем. :)

  3. Я был бы осторожен с именами методов с префиксом new, так как это имеет некоторое значение для Objective-C (см. prefix-leads-to-bad-access-error-in-ios">здесь). Вместо этого попробуйте createPath.

person Eric Galluzzo    schedule 11.01.2016

С компилятором дело в том, что если вы называете функцию с помощью newXXX, вам нужно управлять своей памятью. Итак, в -otherFunction

-(NSArray*)otherFunction
{
    CGPathRef ref = [self newPath];
    UIBezierPath *path = [UIBezierPath bezierPathWithCGPath: ref];
    NSArray* paths = @[path];
    return paths;
}

после создания UIBezierPath вы должны позвонить

CGPathRelease(ref);
person cekisakurek    schedule 11.01.2016