2

I've looked at each posted question on this topic, but none give me a solution. My project replicates to a large extent the AVPlayer demo app in the dev library (minus the scrubbing capabilities): I have a copy and paste AVPlayerDemoPlaybackView class (renamed YOPlaybackView) and an associated controller, along with a very similar xib (minus the scrubber). My view controller code follows very closely the pattern in the demo (code differences only posted below for brevity).

  • I have ensured the view controller is the file's owner

  • I have made sure outlets are not duplicated

  • I have checked that the view controller is a valid instance by putting a breakpoint in dealloc

    The error occurs in the observeValueForKeyPath method when the current item for the player changes/will change. The following line gives the error "-[UIView SetPlayer:]": unrecognised selector sent to instance ..."

         [playbackView setPlayer:player];
    

If I create an instance of that view just prior to this call, I don't get the error:

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

It seems to me that it might be something to do with nib lazy loading (and creating an instance kicks it in to life).

Looking in the debugger window, playbackView seems to be valid with and without the extra line that creates an (unused) instance.

enter image description here

Can anyone help progress my object/app lifecycle knowledge please?


Edit - in response to proposed answer containing IB comment

This is a snap of the IB, showing the view hierarchy and correctly named custom view in the inspector. enter image description here

Edit - in response to question about valid SetPlayer

The view class in question looks like this:

 @class AVPlayer;

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

and impl:

 @implementation YOPlaybackView

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

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

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

 @end

Edit - output log

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)
Community
  • 1
  • 1
eggfish
  • 65
  • 1
  • 7
  • Do you have a valid `setPlayer` method in your `YOPlaybackView` subclass? – Rog Jul 23 '13 at 10:23
  • I have added the class declaration and implementation as an edit - thanks. – eggfish Jul 23 '13 at 10:40
  • What is missing is the line where it says `YOPlaybackView * playbackView = ....` – Felix Lamouroux Jul 23 '13 at 10:41
  • As I mention in my answer `playbackView` is not pointing to an instance of `YOPlaybackView`. – Felix Lamouroux Jul 23 '13 at 10:42
  • Thanks @FelixLam for the help. As I understood it, the classes in the nib, including YOPlaybackView, are created by the framework when the nib is loaded? In the Apple demo app there is no explicit creation of their AVPlayerDemoPlaybackView in any code, so I based my assumption on that. This view has a toolbar child for instance, and that gets automatically created - I don't need to explicitly create a UIToolbar in my code? – eggfish Jul 23 '13 at 10:55
  • You're sure it's the above line giving the error and not something inside setPlayer, et al? – Hot Licks Jul 23 '13 at 10:58
  • @HotLicks - yes I have put a try-catch block round "[playbackView setPlayer:player];" to catch and view the exception. – eggfish Jul 23 '13 at 11:01
  • The delay seems to be related to instantiating AVAudioPlayer for the first time. If I load any audio, run `[audioPlayer prepareToPlay]` and then immediately release it, the load times for all of my other audio is very close to imperceptible. So now I'm doing that in applicationDidFinishLaunching and everything else runs well. – 9to5ios Jul 23 '13 at 11:08
  • It would be good to see the call stack at the time of this error, to know where in the load sequence you're invoking this function. I'm wondering if there's a timing problem of some sort, and the extra alloc/init just provides a time delay. – Hot Licks Jul 23 '13 at 11:39
  • Hi I am also facing same issue. Earlier when I was running my app on iOS 8.x.x everything works fine but when I switched to iOS 9, app is getting crash with same error as above mentioned. – Gagan_iOS Oct 20 '15 at 08:19

2 Answers2

1

Your playbackView appears to be an instance of UIView which does not have a method called setPlayer:. Check that you are creating an instance of your own subclass of UIView. Could you post the snippet of code where you create the playbackView?

If you are using Interface Builder make sure that you have set the correct class in the inspector.

You will need to reference the class somewhere in your code. Try Adding [YOPlaybackView class] right above the setPlayer: call.

Felix Lamouroux
  • 7,414
  • 29
  • 46
  • Yes I'm using IB. I have a top level view (UIView) with a child view (YOPlaybackView - set in inspector). My file owner is changed to my custom view controller, and my outlets are correctly wired up as far as I can see (double-checked). Added snapshot of IB. – eggfish Jul 23 '13 at 10:45
  • 1
    Can you add `NSLog(@"%@", playbackView);` just before the setPlayer call and post the output – Felix Lamouroux Jul 23 '13 at 11:02
  • Now getting somewhere - added as edit to question. Seems the IB file doesn't know what the class YOPlaybackView is-(http://stackoverflow.com/questions/1725881/unknown-class-myclass-in-interface-builder-file-error-at-runtime) – eggfish Jul 23 '13 at 11:06
0

Using @FelixLam's very helpful advice I managed to get more log output data, which is now inserted as the third edit in the question. The first line output states that the Interface Builder does not know what my custom view class was. With a bit of searching on the site I came across the answer to that problem here ("Unknown class <MyClass> in Interface Builder file" error at runtime) - which turns out to be the answer to my question as well.

In short, the linker flag "-ObjC" must be added to the project, which forces the linker to load the members of the class.

Community
  • 1
  • 1
eggfish
  • 65
  • 1
  • 7
  • Hi @FelixLam, once again thanks for helping. For my understanding, can you explain why your proposal of adding e.g. "[YOPlaybackView class]" to kick it in to life is a better solution than adding the inker flag -ObjC? Is it for efficiency sake so that you are not loading everything? Thanks – eggfish Jul 24 '13 at 13:11
  • This leads to smaller binaries and avoids loading everything. See http://stackoverflow.com/questions/6629979/what-does-the-objc-linker-flag-do – Felix Lamouroux Jul 24 '13 at 14:17