Ошибка неверного доступа при доступе к UIColor * - PullRequest
1 голос
/ 21 сентября 2009

В моей процедуре рисования для пользовательского UITableViewCell без проблем использовалось следующее:

CGContextRef context = UIGraphicsGetCurrentContext();   
UIColor* backgroundColor = [UIColor colorForHex:@"FFFEFF"];
[backgroundColor set];
CGContextFillRect(context, rect);

Конечно, это довольно стандартно, за исключением моего интерфейса для объекта UIColor для colorForHex, который принимает строку и разбивает ее на значения RGB 0-255 и возвращает объект UIColor со следующим (a по умолчанию равен 1.0f ):

return [UIColor colorWithRed:((float) r/255.0f) green:((float) g/255.0f) blue:((float) b/255.0f) alpha:a];

Теперь это работает нормально, но я попытался улучшить это и централизовать создание цвета (и шрифта), чтобы попытаться максимально ускорить процедуру рисования. Вот где у меня проблема.

Я создаю протокол, используя:

@protocol ItemListTableViewCellDelegate
-(UIFont*) fontForId:(int) fontID;
-(UIColor*) colorForId:(int) colorID;
@end

Контроллер реализует этот протокол и реализует метод colorForId как:

-(UIColor*) colorForId:(int) colorID {
    UIColor* requestedColor = nil;
    switch (colorID) {
        case BACKGROUND_COLOR_ID:
        {
            requestedColor = backgroundColor;
        }
            break;
    }
    return requestedColor;
}

где backgroundColor создается как элемент контроллера как UIColor * в методе initWithStyle контроллера. Это вызывается и создается backgroundColor.

В ячейке есть элемент NSObject<ItemListTableViewCellDelegate>* cellDelegate, который инициализируется контроллером, чтобы ячейка могла вызывать

UIColor* backgroundColor = [cellDelegate colorForId:BACKGROUND_COLOR_ID]; 

, который, по-видимому, возвращает правильный указатель на UIColor в контроллере, но когда для этого цвета в методе рисования ячейки вызывается 'set', ячейка выдает ошибку BAD ACCESS, и я не могу понять, почему. 1021 *

Есть ли указатели в правильном направлении?

1 Ответ

2 голосов
/ 21 сентября 2009

Для любых ошибок EXC_BAD_ACCESS вы обычно пытаетесь отправить сообщение освобожденному объекту. ЛУЧШИЙ способ отследить это - использовать NSZombieEnabled .

Это работает, никогда не выпуская объект, а заключая его в «зомби» и устанавливая внутри него флаг, который говорит, что обычно он был бы выпущен. Таким образом, если вы попытаетесь снова получить к нему доступ, он все еще будет знать, что было до того, как вы допустили ошибку, и с помощью этой небольшой информации вы, как правило, можете вернуться, чтобы увидеть, в чем проблема.

Это особенно помогает в фоновых потоках, когда отладчик иногда выбрасывает любую полезную информацию.

ОЧЕНЬ ВАЖНО ЗАМЕЧАНИЕ однако, вам нужно на 100% убедиться, что это только в вашем отладочном коде, а не в коде дистрибутива. Поскольку ничего не выпускается, ваше приложение будет течь и течь и течь. Чтобы напомнить мне сделать это, я поместил этот журнал в моем appdelegate:

if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
...