ARC и освобождение памяти - PullRequest
       5

ARC и освобождение памяти

3 голосов
/ 19 декабря 2011

Я прочитал много статей в Интернете, и я немного запутался в ARC. Я перечислю свои вопросы ниже, пожалуйста, помогите мне ответить на них.

1.) Что делает ключевое слово strong@property (nonatomic, strong) …)?

2.) Разве нам больше не нужно release или autorelease тому, что мы alloc, потому что я получаю предупреждение о том, что мне это не нужно. (Я не на своем Mac, поэтому я не могу скопировать полученное предупреждение.)

3.) Я не смог найти инструмент Leaks в Xcode 4.2. Куда это делось? Или нам не нужно больше проверять утечки?

4.) При создании проекта с использованием Xcode 4.2 я нажал «включить ARC», так будет ли моя программа работать на iOS 3? (Я думаю, что ARC поддерживает только iOS 4 и выше.)

Ответы [ 3 ]

7 голосов
/ 19 декабря 2011
  1. strong - это аналог ARC для retain (в ARC нет retain). Это означает, что значение свойства будет храниться в классе, где @property был определен и освобожден после переназначения или освобождения. (Обратите внимание, что в ARC нет необходимости освобождать или аннулировать свойства в dealloc).

  2. Смысл ARC в том, что компилятор заботится о рутине retain / release, поэтому нет необходимости в ручных методах управления памятью.

  3. Вы можете проверить наличие утечек, запустив Профиль (меню Product -> Profile) и выбрав инструмент утечки. Утечки могут быть введены с помощью циклических ссылок или в коде CoreFoundation (ARC не работает с CoreFoundation). Также, если вы смешиваете ARC и не-ARC код, последний может быть источником утечек.

  4. ARC поддерживается ОС начиная с iOS 4.0 (хотя необходим iOS 5 SDK). Основное различие между поддержкой ARC 4.0 и 5.0 заключается в доступности спецификатора свойства weak. Слабое свойство (переменная __weak) будет автоматически аннулировано при освобождении значения strong, на которое оно ссылается. В 4.0 нет свойств weak, поэтому следует использовать спецификатор __unsafe_unretained (он близок к описателю assign, он не сохраняет значения и может указывать на уже освобожденное значение, поэтому это опасно).

Вот отличное объяснение ARC: Все, что вам нужно знать об автоматическом подсчете ссылок

6 голосов
/ 19 декабря 2011
  1. Сильный эквивалентен retain в ARC. Это указывает на владение: Что делает ключевое слово "strong"

  2. Нет, это сделано для вас. ARC автоматически вставляет эти операторы в (скомпилированный) код. Это его основная работа. Но, согласно комментарию Абизерна, это работает только для ваших объектов и объектов Какао. Если вы используете базовые базовые (CF*) классы, вы должны прочитать о семействе приведений __bridge. Вы можете начать читать здесь.

  3. Это в инструментах. В ответ на iHunter, Cmd + I или Product-> Profile, затем выберите Leaks. Особенно важны данные (2).

  4. Не будет работать.

2 голосов
/ 19 декабря 2011

Ну, есть уже три ответа, которые охватывают основные вещи, поэтому я сосредоточусь на одной детали, которая еще не упомянута:

3.) Я не смог найти инструмент Leaks в Xcode 4.2. Куда это делось? Или мы не должны больше проверять утечки?

Да, нам все еще нужно проверить на утечки:

ARC - это не сборщик мусора, это автоматическое сохранение / освобождение.

Таким образом, все еще возможно - на самом деле, довольно легко - создавать утечки!

Рассмотрим следующий пример:

@class Puppet;
@protocol PuppetDelegate : <NSObject>
- (void)puppetDidTwistStrings:(Puppet *)puppet;
@end

@interface Puppet : NSObject {
    id <PuppetDelegate> delegate_;
}

- (id)initWithPuppetDelegate:(id <PuppetDelegate>)delegate;
- (void)unravelStrings;

@end

@implementation Puppet
- (id)initWithPuppetDelegate:delegate
{
    if (!(self = [super init])) return nil;

    delegate_ = delegate;

    return self;
}

// assume some implementation for unravel strings

@end

@interface MasterOfPuppets : NSObject <PuppetDelegate> {
    NSMutableArray *puppets_;
}

- (void)puppetDidTwistStrings:(Puppet *)puppet;
- (void)bringOutAPuppet;

@end

@implementation
- (id)init
{
     if (!(self = [super init])) return nil;

     puppets_ = [[NSMutableArray alloc] init];

     return self;
}

- (void)bringOutAPuppet
{
    Puppet *newPuppet = [[Puppet alloc] initWithPuppetDelegate:self];
    [puppets_ addObject:newPuppet];
}

- (void)puppetDidTwistStrings:(Puppet *)puppet
{
    BOOL isOurPuppet = [puppets_ containsObject:puppet];
    if (!isOurPuppet) return;

    [puppet unravelStrings];
}
@end

Этот пример (по общему признанию) немного глуп, но этот код утечет, и ARC не поможет вам в этом, тогда как сборка мусора:

  • У MasterOfPuppets может быть много марионеток, которые он хранит в переменной экземпляра - пока все хорошо.
  • У Puppet есть делегат, который собирается сообщить, запутаны ли его строки - и вот он начинается.

В то время как в коде, отличном от ARC, переменная экземпляра была просто указателем, который был назначен, ARC предполагает, что если вы храните что-то в переменной, вы хотите за нее цепляться, и она будет retain значение, если только Вы Скажите это не.

Итак, у вас есть классический цикл сохранения, и ARC не спасет вас от них.

Это может показаться надуманным и надуманным примером, но это не так: я довольно часто видел это в отношениях делегатов.

(Кстати, решение довольно простое: объявите Puppet переменную экземпляра *1035* как weak и все будет работать как надо.)

...