Еще одна проблема - «Неопознанный селектор отправлен в экземпляр».

Я просмотрел каждый заданный вопрос по этой теме, но ни один из них не дал мне решения. Мой проект в значительной степени реплицирует демонстрационное приложение AVPlayer в библиотеке разработчика (без возможности очистки): у меня есть копия и вставка класса AVPlayerDemoPlaybackView (переименованный в YOPlaybackView) и связанный с ним контроллер, а также очень похожий xib (без ползунка) . Мой код контроллера представления очень точно следует шаблону в демонстрации (различия кода указаны ниже для краткости).

  • Я убедился, что контроллер представления является владельцем файла.

  • Я убедился, что розетки не дублируются

  • Я проверил, является ли контроллер представления допустимым экземпляром, поставив точку останова в dealloc

    Ошибка возникает в методе observeValueForKeyPath при изменении / изменении текущего элемента для плеера. Следующая строка выдает ошибку - [UIView SetPlayer:]: неопознанный селектор отправлен в экземпляр ...

         [playbackView setPlayer:player];
    

Если я создаю экземпляр этого представления непосредственно перед этим вызовом, я не получаю сообщение об ошибке:

        YOPlaybackView* vw = [[YOPlaybackView alloc] init];
        [playbackView setPlayer:player];

Мне кажется, что это может быть связано с ленивой загрузкой пера (и создание экземпляра запускает его в жизнь).

Глядя в окно отладчика, кажется, чтоplayView действителен с дополнительной строкой, которая создает (неиспользуемый) экземпляр, и без нее.

введите описание изображения здесь

Может ли кто-нибудь помочь улучшить мои знания о жизненном цикле объекта / приложения?


Изменить - в ответ на предложенный ответ, содержащий комментарий ИБ

Это снимок IB, показывающий иерархию представлений и правильно названный настраиваемый вид в инспекторе. введите описание изображения здесь

Изменить - в ответ на вопрос о действующем SetPlayer

Рассматриваемый класс представления выглядит так:

 @class AVPlayer;

 @interface YOPlaybackView : UIView
 @property (nonatomic, retain) AVPlayer* player;
 - (void)setPlayer:(AVPlayer*)player;
 @end

и подразумевают:

 @implementation YOPlaybackView

 + (Class)layerClass
 {
   return [AVPlayerLayer class];
 }

 - (AVPlayer*)player
 {
   return [(AVPlayerLayer*)[self layer] player];
 }

 - (void)setPlayer:(AVPlayer*)player
 {
   [(AVPlayerLayer*)[self layer] setPlayer:player];
 }

 @end

Правка - вывод журнала

2013-07-23 12:05:39.084 iOSVideoPlayerExample[8331:14003] Unknown class YOPlaybackView in Interface Builder file.
2013-07-23 12:05:39.956 iOSVideoPlayerExample[8331:14003] Unbalanced calls to begin/end appearance transitions for <YOMasterViewController: 0x985aa10>.
2013-07-23 12:05:40.428 iOSVideoPlayerExample[8331:14003] <UIView: 0x8383900; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x8381710>>
2013-07-23 12:05:40.429 iOSVideoPlayerExample[8331:14003] -[UIView setPlayer:]: unrecognized selector sent to instance 0x8383900
(lldb)

person eggfish    schedule 23.07.2013    source источник
comment
У вас есть допустимый setPlayer метод в вашем YOPlaybackView подклассе?   -  person Rog    schedule 23.07.2013
comment
Я добавил объявление и реализацию класса в качестве редактирования - спасибо.   -  person eggfish    schedule 23.07.2013
comment
Чего не хватает, так это строки, в которой написано YOPlaybackView * playbackView = ....   -  person Felix Lamouroux    schedule 23.07.2013
comment
Как я уже упоминал в своем ответе, playbackView не указывает на экземпляр YOPlaybackView.   -  person Felix Lamouroux    schedule 23.07.2013
comment
Спасибо @FelixLam за помощь. Как я понял, классы в пере, в том числе YOPlaybackView, создаются фреймворком при загрузке перья? В демонстрационном приложении Apple нет явного создания их AVPlayerDemoPlaybackView в каком-либо коде, поэтому я основывал свое предположение на этом. Например, у этого представления есть дочерняя панель инструментов, которая создается автоматически - мне не нужно явно создавать UIToolbar в моем коде?   -  person eggfish    schedule 23.07.2013
comment
Вы уверены, что это строка выше дает ошибку, а не что-то внутри setPlayer и др.?   -  person Hot Licks    schedule 23.07.2013
comment
@HotLicks - да, я поставил блокировку try-catch вокруг [playView setPlayer: player]; чтобы поймать и просмотреть исключение.   -  person eggfish    schedule 23.07.2013
comment
Задержка, похоже, связана с созданием экземпляра AVAudioPlayer в первый раз. Если я загружаю какой-либо звук, запускаю [audioPlayer prepareToPlay], а затем немедленно освобождаю его, время загрузки для всех остальных моих аудио очень близко к незаметному. Итак, теперь я делаю это в applicationDidFinishLaunching, а все остальное работает хорошо.   -  person 9to5ios    schedule 23.07.2013
comment
Было бы хорошо увидеть стек вызовов во время этой ошибки, чтобы знать, где в последовательности загрузки вы вызываете эту функцию. Мне интересно, есть ли какая-то проблема с синхронизацией, а дополнительный alloc / init просто обеспечивает временную задержку.   -  person Hot Licks    schedule 23.07.2013
comment
Привет, я тоже столкнулся с той же проблемой. Раньше, когда я запускал свое приложение на iOS 8.x.x, все работало нормально, но когда я переключился на iOS 9, приложение вылетало с той же ошибкой, что и выше.   -  person Gagan_iOS    schedule 20.10.2015


Ответы (2)


Ваш playbackView выглядит экземпляром UIView, у которого нет метода с именем setPlayer:. Убедитесь, что вы создаете экземпляр своего собственного подкласса UIView. Не могли бы вы опубликовать фрагмент кода, в котором вы создаете playbackView?

Если вы используете Interface Builder, убедитесь, что вы установили правильный класс в инспекторе.

Вам нужно будет ссылаться на класс где-нибудь в вашем коде. Попробуйте Добавить [YOPlaybackView class] прямо над вызовом setPlayer:.

person Felix Lamouroux    schedule 23.07.2013
comment
Да, я использую ИБ. У меня есть представление верхнего уровня (UIView) с дочерним представлением (YOPlaybackView - устанавливается в инспекторе). Мой владелец файла изменен на мой настраиваемый контроллер представления, и мои розетки правильно подключены, насколько я могу видеть (проверено дважды). Добавлен снимок IB. - person eggfish; 23.07.2013
comment
Можете ли вы добавить NSLog(@"%@", playbackView); непосредственно перед вызовом setPlayer и опубликовать результат - person Felix Lamouroux; 23.07.2013
comment
Теперь кое-что получилось - добавлено как правка к вопросу. Кажется, что файл IB не знает, что такое класс YOPlaybackView - (stackoverflow.com/questions/1725881/) - person eggfish; 23.07.2013

Используя очень полезный совет @ FelixLam, мне удалось получить больше выходных данных журнала, которые теперь вставлены как третье изменение в вопросе. В первой строке выходных данных указано, что Interface Builder не знает, каким был мой пользовательский класс представления. Немного поискав на сайте, я нашел здесь ответ на эту проблему (Неизвестный класс ‹MyClass› в ошибке файла Interface Builder во время выполнения), что также является ответом на мой вопрос.

Короче говоря, в проект должен быть добавлен флаг компоновщика «-ObjC», который заставляет компоновщик загружать члены класса.

person eggfish    schedule 23.07.2013
comment
Привет @FelixLam, еще раз спасибо за помощь. Насколько я понимаю, можете ли вы объяснить, почему ваше предложение о добавлении, например, [Класс YOPlaybackView], чтобы оживить его, - лучшее решение, чем добавление флага чернил -ObjC? Это для эффективности, чтобы вы не загружали все? Спасибо - person eggfish; 24.07.2013
comment
Это приводит к уменьшению размера двоичных файлов и позволяет избежать загрузки всего. См. stackoverflow.com/questions/ 6629979 / - person Felix Lamouroux; 24.07.2013