Правильный способ обработки CGImageRef в контейнерах под ARC
Я новичок в использовании дуги в моих проектах. Я пытаюсь понять __bridge и его маленьких друзей, чтобы я мог правильно использовать CGImageRef при добавлении и удалении их из контейнеров.
Я получаю "Потенциальную утечку хранящегося объекта…" на одной из моих строк. Вот основной цикл моего кода:
CGImageRef renderedRef = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());
[_array addObject: (__bridge_transfer id)renderedRef];//_array is an iVar
затем где-то по дороге я делаю это:
CGImageRef iRef = (__bridge_retained CGImageRef)array[0];
//then I do something fancy with iRef
//at the end of the method, I get "Potential leak of an object stored…"
//I have no idea what to do
//I've tried CGImageRelease(iRef); but it still doesn't change the warning.
Может кто-то пролить свет на это? Кроме того, я пробовал просто использовать __bridge, но это не имеет значения.
Изменить 1:
Я расширил результаты анализа и следил за тем, что происходило. Это потому, что я использовал iRef в таком методе: [self doSomethingFancy:iRef]; и в этом методе iRef был сохранен, но не выпущен. Так что это исправляет предупреждение, но я все еще немного озадачен.
Я не совсем понимаю, когда использовать различные __bridge-приведения. Под ARC, увеличивает ли следующий счетчик ссылок?
CGImageRef iRef = (__bridge CGImageRef)array[0];
Кроме того, в какой-то момент, если я скажу своему _array iVar удалить AllObjects, будет ли это правильно уменьшать количество ссылок?
1 ответ
// This WILL NOT increment the image's retain count.
CGImageRef iRef = (__bridge CGImageRef)array[0];
// This WILL increment the image's retain count.
CGImageRef iRef = (__bridge_retained CGImageRef)array[0];
поскольку __bridge_retained
увеличивает счет сохранения, вам нужно уменьшить счет хранения через некоторое время. Так как __bridge_retained
действует как CFRetain
Apple создала __bridge_retained
обертка называется CFBridgingRetain
это напоминает вам об этом:
// This WILL increment the image's retain count.
CGImageRef iRef = CFBridgingRetain(array[0]);
Всякий раз, когда вы видите CFRetain
или же CFBridgingRetain
вы знаете, что вам нужно отпустить объект в какой-то момент позже.
Точно так же вы можете использовать CFBridgingRelease
вместо __bridge_transfer
уменьшить количество сохраняемых объектов CF. Пример:
[_array addObject:CFBridgingRelease(renderedRef)];
Ты можешь использовать CFBridgingRelease
сбалансировать CFRetain
или CFBridgingRetain
, Возвращает id
что ARC управляет.
Нормальный NSMutableArray
сохраняет каждый из его элементов. Вы можете сказать это, чтобы стать пустым:
[_array removeAllObjects];
Когда вы сделаете это, он освободит каждый из своих элементов, уравновешивая сохранение, которое он выполнил для каждого элемента.
Таким образом, в этом коде нет утечки памяти:
CGImageRef image = CGImageCreate(...);
[_array addObject:CFBridgingRelease(image)];
[_array removeAllObjects];
или в этом коде:
CGImageRef image = CGImageCreate(...);
[_array addObject:CFBridgingRelease(image)];
CGImageRef image2 = CFBridgingRetain([_array lastObject]);
[_array removeLastObject];
CGContextDrawImage(gc, rect, image2);
CGImageRelease(image2);