NSSound работает, но не инициализирован или не выделен..

#objective-c #memory #object #methods #memory-management

#objective-c #память #объект #методы #управление памятью

Вопрос:

У меня есть простая программа, которая воспроизводит песню. Это в унаследованном методе awakeFromNib. Итак..

 -(void)awakeFromNib {
NSSound *song = [NSSound soundNamed:@"MyTune.mp3"];
[song play];
}
  

Мой вопрос в том, почему это работает. Почему мне не нужно этого делать

 NSSound *song = [[NSSound alloc]init];
song = [NSSound soundNamed:@"MyTune.mp3"];
[song play];
}
  

Похоже, он также работает и со строками.. У меня настроена переменная NSTextView, и я могу сделать следующее

 -(void)awakeFromNib {
NSString *str = [NSString stringWithFormat:@"Hello there!"];
[myTextVariable insertText:str];
}
  

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

Комментарии:

1. Кто-нибудь? Мне просто трудно это понять.

Ответ №1:

Многие классы Apple имеют вспомогательные функции, объявленные на уровне класса, которые выполняют выделение и инициализацию для вас внутри вспомогательной функции. Они возвращают готовый к использованию объект. Вы можете сказать, видите ли вы документ для метода, и там написано что-то вроде «Возвращает экземпляр NSSound, связанный с заданным именем».

Следовательно, ваш первый пример — хороший код:

 -(void)awakeFromNib {
NSSound *song = [NSSound soundNamed:@"MyTune.mp3"];
[song play];
}
  

Во втором примере происходит утечка памяти, потому что вы выделяете, а затем перезаписываете свой указатель новым объектом, возвращаемым [NSSound soundNamed:@"MyTune.mp3"] :

   -(void)awakeFromNib {

    // Create an NSSound object in memory and store the address in song.
    NSSound *song = [[NSSound alloc]init]; 

    // If you don't want a memory leak this is your last chance to [song release]

    // Create a NSSound object using a helper function and place its address 
    // in song, over writing the previous address.
    song = [NSSound soundNamed:@"MyTune.mp3"];

    // We now lost track of the first NSSound object and can't release it because 
    // we overwrote the address.

    [song play];
    }
  

Из документации вы можете видеть, что этот метод выполняет alloc и init внутри него и возвращает вам экземпляр:

Название звука:

Возвращает экземпляр NSSound, связанный с заданным именем.

(id) Звуковое имя: (NSString *) Звуковое имя

Параметры

soundName Имя, которое идентифицирует звуковые данные.

Возвращаемое значение

Экземпляр NSSound инициализирован звуковыми данными, идентифицированными по soundName.

Комментарии:

1. Хорошо, допустим, во втором примере я включаю [выпуск песни]; будет ли это то же самое?

2. Вы не освобождаете его, поскольку вы его не выделяли. Когда вы используете вспомогательную функцию, код Apple будет управлять выпуском для вас. Он делает это, потому что он выделил его.

3. Думаю, я не понял, что вы имеете в виду. Если вы спрашиваете о вставке релиза между строками 2 и 3 во втором примере, то да. Функционально это было бы то же самое, что и в первом примере, но пустая трата циклов процессора и кодирования.

4. Спасибо Ричарду, да, это то, о чем я спрашивал. В принципе, если бы я вставил [выпуск песни]; ПОСЛЕ [воспроизведения песни];, то это устранило бы утечку…

5. Кроме того, я не знал о вспомогательной функции. Есть ли простой способ определить, в каких классах он есть?