EXC_BAD_ACCESS при вызове drawRect для сохраненного UIImage - PullRequest
1 голос
/ 27 сентября 2011

У меня странная проблема.Я создаю UIImage с imageNamed, извлекаем из него данные о цвете и затем устанавливаю его в другой класс.

Затем из этого класса, когда я делаю drawRect, я получаю EXC_BAD_ACCESS при выполнении drawRect.

Здесьвот где я загружаю изображение:

UIImage*    pImageHM    = [UIImage imageNamed:@"Heatmap2.png"];
CGImageRef  irHM        = [pImageHM CGImage];
CFDataRef   drHM        = CGDataProviderCopyData( CGImageGetDataProvider( irHM ) );
R8G8B8A8*   pDataHM     = (R8G8B8A8*)CFDataGetBytePtr( drHM );

unsigned int colour     = 0;
unsigned int colourMax  = 256;
while( colour < colourMax )
{
    // Extract image data.
    colour++;
}
[mpView SetScale: pImageHM];

CFRelease( drHM );
CGImageRelease( irHM );

Функция SetScale определяется следующим образом:

- (void) SetScale: (UIImage*)pImage
{
    [mpScale release];

    mpScale = pImage;

    [mpScale retain];

    [self setNeedsDisplay];
}

И, наконец, я отрисовываю его следующим образом:

    CGContextRotateCTM( ctx, -M_PI_2 );
    CGContextTranslateCTM( ctx, -(rect.size.height - 48), 0);

    [mpScale drawInRect: CGRectMake( 0,                    rect.size.width - 16,
                                    rect.size.height - 48, 16 )];

    CGContextTranslateCTM( ctx, (rect.size.height - 48), 0 );
    CGContextRotateCTM( ctx, M_PI_2 );

Зачем mpScale поднять EXC_BAD_ACCESS?Учитывая, что UIImage был сохранен, тот факт, что он был впоследствии автоматически выпущен после того, как я вызвал SetScale, не должен быть ни здесь, ни там.

Я должен добавить, что если я не вызываю SetScale (такой, что mpScale остается равным nil), то я не получаю сбоев и, очевидно, я не вижу ничего там, где должен быть масштаб.

Заранее спасибо!

Ответы [ 3 ]

4 голосов
/ 27 сентября 2011

CGImageRef irHM = [pImageHM CGImage];

Вам не принадлежит этот CGImage, но вы выпускаете его.

CGImageRelease( irHM );

2 голосов
/ 27 сентября 2011

У вас есть несколько проблем здесь:

  • Ваш метод SetScale не соответствует Соглашения о присвоении имен какао (см. Здесь) . Назовите его setScale с префиксом «set» в нижнем регистре, чтобы его можно было считать установщиком (и, следовательно, разрешить работу KVC, автоматическую запись в точках и т. Д.)

  • Вы должны проверить, что mpImage и pImage не являются одним и тем же объектом при реализации сеттера setScale. Если вы этого не сделаете, вы получите EXC_BAD_ACCESS (возможно, тот, который у вас есть, тогда), потому что вы отпустите объект до того, как на него воздействуете + сохраните его, так что он достигнет нулевого значения retainCount, прежде чем у вас появится возможность сохранить его снова.

Ваш сеттер должен быть:

-(void)setScale:(UIImage*)pImage
{
    // only do this if the variables don't point to the same object in memory to avoid crash
    if (mpImage != pImage) {
        [mpImage release]; // release old value
        mpImage = [pImage retain]; // retain new one
    } 
}

Более того (и это реальная причина вашего EXC_BAD_ACCESS) , вы выпускаете irHM (CGImageRelease в последней строке вашего кода), но вы не должны (вы этого не сделали сохранить его или вступить во владение им раньше)

CGImageRef  irHM        = [pImageHM CGImage];
CFDataRef   drHM        = CGDataProviderCopyData( CGImageGetDataProvider( irHM ) );
...
[mpView SetScale: pImageHM];

CFRelease( drHM ); // <-- that's ok because you did use a "...Copy..." method
// CGImageRelease( irHM ); // <-- you DON'T need nor should do that !!
1 голос
/ 27 сентября 2011

В случае pImage == mpScale, когда вы звоните SetScale, вы снимаете изображение, устанавливаете его, затем ничего не сохраняете. mpScale в этот момент будет указывать на недопустимый объект.

...