/ / Странно поведение на паметта със статичен инициализатор на AVQueuePlayer - ios, aim-c, управление на паметта, автоматично преброяване на ref

Странно поведение на паметта със статичен инициализатор на AVQueuePlayer - ios, цел-c, управление на паметта, автоматично преброяване

Декларирах имот

@property(nonatomic, strong) AVQueuePlayer *player;

и когато го инициализирам с + queuePlayerWithItems: той не е разместен, ако го възлагам player нов обект или нула. Дори и да го направя веднага след един ред по-долу. Когато се инициализирам player с – initWithItems: всичко работи според очакванията. Използвам ARC. Това е грешка или не са статични инициализатори с автоматично освобождаване или каква е разликата? Спомням си времената преди ARC, когато би било така

+ (AVQueuePlayer *)queuePlayerWithItems:(NSArray *)items
{
return [[[AVQueuePlayer alloc] initWithItems:items] autorelease];
}

И така, какъв е въпросът?

Отговори:

0 за отговор № 1

С ARC вашият код може да изглежда така:

+ (AVQueuePlayer *)queuePlayerWithItems:(NSArray *)items
{
return [[AVQueuePlayer alloc] initWithItems:items];
}

Компилаторът може все пак поставете създадения обект в пул за автоматично освобождаване. Дали това се случва или не, зависи и от зададеното ниво на оптимизация и дали семейство метод правилно се разпознава.

Можете да помогнете на компилатора да декларира метода по този начин:

+ (AVQueuePlayer *)queuePlayerWithItems:(NSArray *)items NS_RETURNS_RETAINED;

Това ще накара компилатора да приеме, че методът връща разпределен обект и трябва да бъде изпратен балансиран release съобщение, когато е подходящо, вместо да поставите обекта в пула за автоматично освобождаване.

NS_RETURNS_RETAINED ще се разшири до __attribute__((ns_returns_retained))

Определението трябва да пропусне атрибута NS_RETURNS_RETAINED.

Редактиране:

Ако това не е вашият метод и ако не можете да промените декларацията, можете да използвате изричен пул за автоматично освобождаване, за да се отървете от автоматично пуснатия обект:

{
AVQueuePlayer* player;
@autoreleasepool {
// the next line retains the returned object:
player = [AVQueuePlayer queuePlayerWithItems:items];
}  // here, the autorelease pool releases the returned object (it"s still alive)
// do something with variable player:
...
[player ...];  // last usage of variable player
// now, the last reference to player ceases to exist, it gets released and deallocated

}