2012-04-12 3 views
0

Я создал свойство для NSArray, которое создает геттер/сеттер. Я знаю, что Apple рекомендует использовать переменную экземпляра в методе init и dealloc. Я пытаюсь понять, что делать в следующем коде.iPhone init метод issue

(1) Нужна ли дополнительная инструкция по выпуску? Если бы массив не имел счет сохранения 2, а затем 1 с dealloc, оставьте утечку. Или автореферат позаботится об этом?

(2) Существует ли какой-либо способ в xCode или инструментах следовать определенной переменной, чтобы увидеть, как ее счет сохраняется в процессе.

@property (nonatomic, retain) NSArray *array; 

@synthesize arrary = _array; 

- (id)initWithNibName:(NSString *)nibNameOrNil 
       bundle:(NSBundle *)nibBundleOrNil 
     initWithArray:(NSArray *)array 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 

     _array = [[NSArray alloc] initWithArray:array]; 

    } 
    return self; 
} 

- (void)dealloc 
{ 
    [_array release]; 

    [super dealloc]; 
} 
+0

Что «результаты» в '[[NSArray alloc] initWithArray: results];'? – dasblinkenlight

+0

Извините, он должен сказать массив. Просто переданный массив из другого класса – Vikings

ответ

2

(1) Нужна ли дополнительная инструкция по выпуску? Если бы массив не имел счет сохранения 2, а затем 1 с dealloc, оставьте утечку. Или автореферат позаботится об этом?

Давайте пошагово это:

@property (nonatomic, retain) NSArray *array; 

// The setter in this case will do the proper ref counting: 
@synthesize arrary = _array; 

- (id)initWithNibName:(NSString *)nibNameOrNil 
       bundle:(NSBundle *)nibBundleOrNil 
     initWithArray:(NSArray *)array 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     // _array is nil at allocation 
     _array = [[NSArray alloc] initWithArray:array]; // << self holds one reference 

    } 
    return self; 
} 

- (void)dealloc 
{ 
    [_array release]; // << self holds zero references 
    [super dealloc]; 
} 

Другими словами, вы потребность больше ничего. Лично я бы просто использовал copy в инициализаторе и для свойства (в отличие от retain).

(2) Есть ли какой-либо способ в xCode или инструментах следовать определенной переменной, чтобы увидеть, как ее счет задерживается в процессе.

Да. Однако есть несколько сокращений времени выполнения и исключения из этого.

Самый простой способ - просто запустить инструменты с помощью инструмента распределения, а затем включить запись счетчика ссылок. Затем он будет записывать обратную линию и время для каждого пересчета каждого отдельного объекта.

+0

Спасибо, вы упомянули копию, как бы вы использовали это в ситуациях, когда вы передаете переменные через init? – Vikings

+0

@Vikings с объявленным как '@property (неатомным, копированием) NSArray * array;' и инициализатором '_array = [array copy];' (хотя '_array = [[NSArray alloc] initWithArray: array];' выполняет тоже самое). – justin

0

Edit: Измененный в соответствии с рекомендациями компании Apple. Комментарии, следующие за этим ответом, относятся к моей оригинальной (и очень плохой) версии. В будущем я буду уделять должное внимание Practical Memory Management в iOS Developer Library.

Вопрос (1): Нет, вам не нужен дополнительный выпуск. После [[ASArray alloc] initWithArray:array] ваш массив будет иметь счетчик 1. В dealloc звонок [_array release] вернет его на 0, и он должен быть освобожден.

Если [setArray:] вызывается в то же время, он будет подчиняться его свойства декларации retain путем сохранения нового объекта и отпускания старого.

Если какой-либо другой объект или метод сохраняет ваш массив, это их обязанность освободить его. Если значение сохранения вашего массива больше 1 в начале dealloc, некоторый другой объект сохраняет его, по крайней мере, временно.

Вопрос (2): Вы можете проверить retainCount во время выполнения, но как NSObject Protocol Reference предупреждает, что это легко для вашего объекта оказаться в нескольких бассейнах autorelease, что делает его счет бесцельно высокой.

Бонус: Вы можете думать, что [[NSArray alloc] initWithArray:array] будет использовать сохранить кол входа и добавить 1. Это происходит только в том случае, если «копия» выполняется путем сохранения и передачи ссылки на неизменяемый источник, и в этом случае другой объект также сохраняет ссылку на этот источник. [[NSString alloc] initWithString:] определяет, является ли его источник неизменным и делает это; [[NSArray alloc] initWithArray:] нет. [NSArray copy], с другой стороны, сохранит и вернет себя.

Эти оптимизации, конечно, специфичны для реализации и никогда не должны приниматься. Тем не менее, это может быть поучительно, чтобы построить некоторые объекты, избегая autorelease, и следить за их адреса и retainCounts, как это:

NSArray *array1 = [[NSArray alloc] initWithObjects:@"a", nil]; 
// Do not just assign array1 to [[NSArray alloc] init], or you'll get a singleton empty array with a high retain count. 
// Make array1 mutable, and array2 should be copied differently. 
NSLog(@"Constructed array1"); 
NSLog(@"array1 address = %p retainCount = %d", array1, [array1 retainCount]); 
NSArray *array2 = [array1 copy]; 
// Use [[NSArray alloc] initWithArray:] and the results may be different. 
NSLog(@"Constructed array2"); 
NSLog(@"array1 address = %p retainCount = %d", array1, [array1 retainCount]); 
NSLog(@"array2 address = %p retainCount = %d", array2, [array2 retainCount]); 
[array1 release]; 
NSLog(@"Released array1"); 
NSLog(@"array2 address = %p retainCount = %d", array2, [array2 retainCount]); 
[array2 release]; 
+0

Но будьте осторожны ... этот код приведет к переопределению -> self.array = [[NSArray alloc] initWithArray: array] – borrrden

+0

@borrrden, если я авторекламу после того, как я выделил, это должно позаботиться о это правильно, или есть более элегантный способ – Vikings

+0

@Vikings Да, это способ сделать это, если вы используете свойство для его назначения. Или вы можете сделать то, что вы сделали, и присвоить переменной экземпляра. Если Apple рекомендует, чтобы вы это делали, вам следует в полной мере рассмотреть эту рекомендацию :). – borrrden

0
  1. Ваш код выглядит нормально для меня. Вам не нужно добавлять дополнительный выпуск. В вашем методе init значение count для _array равно 1. После освобождения в dealloc вы должны сделать _array = nil, чтобы избежать оборванных указателей.

  2. Для проверки на наличие утечек, вы можете сделать одно или оба из следующих действий:

(я) CMD + Shift + B ---> Это запускает анализ на вашем коде, чтобы определить проблемы, как это.

(ii) Используйте инструменты «Утечки» и «Распределения» в «Инструменты». Здесь вы можете посмотреть распределения и утечки (если есть), которые ваше приложение выполняет во время выполнения. Это очень полезно, и иногда ловит вещи, которые «Анализировать» не ловят.

+0

Установка _array = nil не требуется – Vikings