О CGColor / определение - PullRequest
       29

О CGColor / определение

2 голосов
/ 17 апреля 2019

В классе у меня есть переменная myColor типа CGColorRef, объявленная следующим образом:

@implementation MyClass
{
    .......
    CGColorRef myColor;
    .......

Вот две строки кода Objective C:

Первая строка:

myColor=[UIColor orangeColor].CGColor;

Вторая строка:

myColor=[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000].CGColor;

Сначала я ожидал, что они эквивалентны, но это не так.

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

Может кто-нибудь объяснить разницу?Надеемся, что это позволит мне изменить мой код и использовать вторую строку.

Просто для справки, он падает (with: Поток 1: EXC_BAD_ACCESS (code = 1, address = 0x881b370e0)):

- (void)drawRect:(CGRect)rect
{
    .......
    CGContextSetStrokeColorWithColor(context,myColor); // Crash here !!!
    CGContextStrokeEllipseInRect(context, rectangle);
    .......
}

Ответы [ 2 ]

3 голосов
/ 17 апреля 2019

Вы назначаете переменную экземпляра типа Core Foundation CGColorRef. Этот тип не является типом объектов ObjC, поэтому не подлежит ARC (автоматическому управлению памятью), что означает, что вам нужно управлять его памятью вручную.

Оба ваших примера на самом деле неверны, но причина, по которой вы изначально не видите сбой при назначении [UIColor orangeColor].CGColor, заключается в счастливом совпадении: объект оранжевого цвета, вероятно, является долгоживущим одноэлементным объектом, и его Внутренняя ссылка CGColor, таким образом, также является долгоживущей, поэтому ваше назначение на ivar работает, а последующий доступ работает - но это всего лишь красная (оранжевая?) сельдь.

Вы действительно видите сбой в другом случае, потому что объект UIColor, который вы создаете при передаче, немедленно освобождается, потому что он больше не используется. Таким образом, значение CGColorRef, которое вы извлекаете из него и присваиваете своему ивару, также сразу становится недействительным и радиоактивным, если вы попытаетесь использовать его позже.

Чтобы безопасно хранить CGColorRef в своем объекте, вам необходимо владеть им, что в вашем случае означает явное сохранение CGColorRef, полученного от UIColor:

myColor = CGColorRetain([UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000].CGColor);

Или, что еще лучше, можно вообще обойти UIColor и просто использовать функцию, которая напрямую дает вам цветовую ссылку с семантикой создания владения:

myColor = CGColorCreateGenericRGB(1.0, 0.5, 0.0, 1.0);

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

- (void)dealloc 
{
    CGColorRelease(myColor);
}

См. Также этот документ Apple Tech Q & A , который входит почти в тот же пример.


Форма управления памятью, необходимая для объектов Core Foundation (CGColorRef - один из них), очень похожа на более старую, предварительно ARC ObjC ручную систему, где вы увеличиваете счет сохранения в точке, где вы хотите хранить («своя») ссылка, а затем уменьшается (освобождается), когда вам больше не нужно, чтобы она была действительной. В Apple есть хорошие документы о том, как лучше об этом думать. В этом случае назначение ссылки на переменную вашего экземпляра означает, что вы хотите сохранить ее действительной в течение некоторого времени. Обычно вы сохраняете в точке назначения (либо явно, либо путем получения ссылки с помощью Create * ), а затем освобождаете ее, когда объект освобождается.

1 голос
/ 17 апреля 2019

Сбой из-за того, что у вас нет сильного ref (свойства) объекта myColor. Возможно, у вас есть assign свойство

Причина, по которой [UIColor orangeColor] работает, но не [UIColor colorWithRed...

Когда вы используете [UIColor orangeColor], вы не создаете объект; вы получаете ссылку на него, и что-то еще управляет его жизненным циклом.

Когда вы инициируете новый объект UIColor, вы обязаны убедиться, что он по-прежнему действителен при использовании. « assign » не увеличивает количество ссылок объекта; " Сильный " делает.

Надеюсь, это полезно

EDIT

Удалить одно свойство, подобное этому

@property (nonatomic,strong) UIColor * myUIColor;

Теперь, когда вы можете

сделать это как

myUIColor =[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000]

когда вам нужен CGColor

myUIColor. CGColor

...