Работает ли ARC с объектами Core Graphics?

Недавно я начал новый проект с использованием автоматического подсчета ссылок (ARC).
Когда я назначил содержимое CALayer:

UIView* view = ...
UIImage* image = ...
view.layer.contents = image.CGImage

Я получил сообщение об ошибке

Неявное преобразование типа указателя не Objective-C 'CGImageRef' в 'id' запрещено ARC

Простое отбрасывание CGImageRef до id скрывает ошибку, но мне было интересно, правильно ли ARC функционирует правильно?

Ответ 1

Вы действительно должны проверить видеоролики ARC с WWDC 2011. Они доступны на сайте разработчика и открываются через iTunes. Особенно:

• Сессия 323 - Представление автоматического подсчета ссылок

• Сессия 322 - Objective-C Прогресс в глубине

Кроме того, ссылка ARC указывает:

https://developer.apple.com/library/content/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

Как ссылки, так и видео обсуждают Core Graphics (и др.) и как они работают с ARC.

В частности, просмотрите раздел под названием "Управление бесстолкновым мостом"

Во многих приложениях Cocoa вам необходимо использовать объекты типа Core Foundation, независимо от того, из самой основы Core Foundation (например, CFArrayRef или CFMutableDictionaryRef) или из рамок, которые принимают Основные фондовые соглашения, такие как Core Graphics (вы можете использовать типы как CGColorSpaceRef и CGGradientRef).

Компилятор автоматически не управляет временем жизни Core Объекты фонда; вы должны вызвать CFRetain и CFRelease (или соответствующие типоспецифические варианты), как это диктуется Core Основные правила управления памятью (см. Программирование управления памятью Руководство для Core Foundation).

Если вы выбрали между объектами Objective-C и Core Foundation, вы необходимо сообщить компилятору о семантике собственности объекта используя листинг (определенный в objc/runtime.h) или Core Макрос в стиле Foundation (определенный в NSObject.h): [...]

Jörg Jacobsen имеет хороший общий обзор возможностей моста: Управление безплатным мостом в среде ARCed.

__ bridge_retained (n.b.: используйте его только при кастинге с указателя объекта на указатель типа C): я (программист) должен ссылаться на этот объект в течение некоторого времени в темном мире указателей типа C, который непрозрачен для вы, ARC. Поэтому, пожалуйста, не отпускайте этот объект, пока я все еще нужно это. Я (программист) обещаю выпустить его сам (в темноте мир), когда я сделал с ним

__ bridge_transfer (n.b.: используйте его только при кастинге с указателя типа C на указатель объекта): я (программист) передаст вам, ARC, объект, который у меня есть, и что меня больше не интересуют в темноте мир указателей типа C, который непрозрачен для вас. Всякий раз, когда вы, ARC, сделанный с этим объектом, отпустите его самостоятельно, потому что вы знаете в нужное время и, таким образом, избавить меня от какой-то работы, не сделав этого сам.

__ bridge: ARC, вы продолжаете балансировать свои удерживания и релизы, поскольку я продолжаю балансировать мои в темном мире указателей типа C, которые является…. Всякий раз, когда мне нужно держаться за объект в темном мире, я буду сохраните его и отпустите, когда это необходимо. Мне не нужны никакие дополнительный контракт с вами, ARC.

Ответ 2

Несмотря на ссылки, отмеченные Стивом, я считаю, что случай, который вы показываете выше, может быть особенным. Из Переход к заметкам о выпуске ARC обратите внимание на раздел "Компилятор обрабатывает CF-объекты, возвращенные из Cocoa Методы":

Компилятор понимает методы Objective-C, которые возвращают Core Типы фондов соответствуют историческим соглашениям об именах Cocoa (см. Расширенное руководство по управлению памятью). Например, компилятор знает, что в iOS, CGColor, возвращаемый CGColor метод UIColor не принадлежит.

Пример кода, который они предоставляют:

gradientLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor darkGrayColor] CGColor],
                                                 (id)[[UIColor lightGrayColor] CGColor], nil];

полагается на известное возвращение CGColors из этих методов (им не хватает значения cast to id, которое я добавил в вышеприведенном коде, что должно быть исправлено в их документации в ближайшее время).

Потому что [image CGImage] следует соглашениям об именах, я считаю, что CGImage будет правильно соединен здесь. Я думаю, что ваше приведение к id должно быть всем, что вам нужно здесь.

Ответ 3

Один популярный ответ на вопрос layer.contents = (id)image.CGImage - layer.contents = obj_unretainedObject(image.CGImage).

Я делаю =(__bridge id)image.CGImage.