Изначально ваша переменная экземпляра player
установлена на nil
(эквивалент null
в C #), так же как поля ссылок автоматически устанавливаются на null
, когда вы создаете объект в C #.Однако, в отличие от C #, вызов чего-то на nil
ничего не делает (в отличие от броска NullReferenceException
).Следовательно, вам нужно присвоить что-то player
, прежде чем оно сможет что-то сделать;в противном случае вызов молча завершается неудачей.
В C # у вас есть new Foo()
, что фактически делает две вещи: он выделяет память для объекта Foo
, а затем вызывает конструктор в этой выделенной памяти;все за один шаг.В Objective-C эти два шага различны.alloc
выделяет память, а init
является «конструктором».В своем первом фрагменте кода вы пропускаете этап выделения, поэтому ничего не происходит.Вы должны получить правильные результаты, используя это:
player = [AVAudioPlayer alloc];
player = [player initWithContentsOfURL:url error:NULL];
Или, более кратко:
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:NULL];
Также обратите внимание, что методы init
действительно возвращают значение.Важно, чтобы вы использовали его для ссылки на объект впоследствии
id foo = [Foo alloc];
foo = [foo init]; // correct
id foo = [[Foo alloc] init]; // correct too
id foo = [Foo alloc];
[foo init]; // incorrect
Причина в том, что метод init
позволяет возвращать совершенно другой объект;это может быть даже другой класс.Objective-C является языком типа «утка», поскольку возвращаемый тип реализует те же методы, что и класс, который вы рекламируете, - все хорошо.(Например, в Mac OS вы никогда не увидите фактический экземпляр NSString
. Вместо этого вы увидите NSCFString
и пару других.)
Я также рекомендую включить автоматическийсохранить функцию подсчета языка Objective-C, поскольку он освобождает вас от большинства процедур управления памятью (в основном retain
/ release
).