Question

I tried to get the XCode openGL ES template running without the xib files from interface builder. But still getting at this line [(EAGLView *)self.view setContext:context]; an [UIView setContext:]: unrecognized selector sent to instance 0x4b1fac0 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setContext:]: unrecognized selector sent to instance 0x4b1fac0

What I'm doing wrong?

main.mm

int main(int argc, char *argv[]) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, @"myAppDelegate");
    [pool release];
    return retVal;
}

myAppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.viewController = [[myViewController alloc] initWithNibName:nil bundle:nil];
    self.window.rootViewController = self.viewController;
    return YES;
}

myViewController.m

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
{
    EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    if (!aContext) {
        aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
    }
    if (!aContext)
        NSLog(@"Failed to create ES context");
    else if (![EAGLContext setCurrentContext:aContext])
        NSLog(@"Failed to set ES context current");

    self.context = aContext;
    [aContext release];

    [(EAGLView *)self.view setContext:context];
    [(EAGLView *)self.view setFramebuffer];

    if ([context API] == kEAGLRenderingAPIOpenGLES2)
        [self loadShaders];

    animating = FALSE;
    animationFrameInterval = 1;
    self.displayLink = nil; 
    return 0;
}

I removed the default xib from my plist file (and the xib files from the project) and also every IBoutlet. Have I missed anything? I'm guessing my appDelegate is wrong something - but can't figure out what or why. Any help would be highly appreciated.

Was it helpful?

Solution

Definitely you seem to be calling setContext on a standard UIView, rather than on an EAGLView. Your view controller should probably implement -loadView, and do something like this:

- (void)loadView {
    self.view = [[EAGLView alloc] initWithFrame:[UIScreen mainScreen].bounds];
}

One thing that seems odd is that you're initializing your view controller with initWithNibName rather than initWithFrame, which is what I would expect you need to do when doing away with nib/xib files.

Here's what I'm doing, maybe it will help.

(Note that: I have a custom view controller, which has a UIView and a subview which is the EAGLView. (I'm also working on adding an ADBanner subview). I'm not calling 'init' on my controller, its view gets loaded when I try to add it to the window as a subview.)

main.m - similar.

AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{   
    // Create the window programatically:
    window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

    controller = [GLViewController alloc];
    [window addSubview:controller.view];
    glView = [controller.glView retain];

    [window makeKeyAndVisible];

    return YES;
}

ViewController.h:

@interface GLViewController : UIViewController <ADBannerViewDelegate>
{
    EAGLView *glView;
}
@property(nonatomic, retain) /*IBOutlet*/ EAGLView *glView;
@end

ViewController.m:

- (void)loadView 
{
    self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
}

-(void)viewDidLoad
{
    [super viewDidLoad];

    glView = [[EAGLView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    glView.userInteractionEnabled=YES;
    [self.view addSubview:glView];
}

EAGLView.m:

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;// JPS - WARNING: this does not work on iOS 3.2!!!

        self.contentScaleFactor = [UIScreen mainScreen].scale;
        CGSize displaySize = [[UIScreen mainScreen]currentMode].size;
        CGRect displayRect = [UIScreen mainScreen].bounds;

        eaglLayer.frame = displayRect;
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys : [NSNumber numberWithBool : NO], 
                                                     kEAGLDrawablePropertyRetainedBacking, 
                                                     kEAGLColorFormatRGBA8, 
                                                     kEAGLDrawablePropertyColorFormat, nil];

        context = [[EAGLContext alloc] initWithAPI : kEAGLRenderingAPIOpenGLES1];

        if (!context || ![EAGLContext setCurrentContext : context]) {
            [self release];
            return;
        }

        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);

        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer *)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

        // Set up thd display link to sync rendering with vblank
        animating = FALSE;
        displayLinkSupported = FALSE;
        animationFrameInterval = 1;
        displayLink = nil;
        animationTimer = nil;

        // A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
        // class is used as fallback when it isn't available.
        NSString *reqSysVer = @"3.1";
        NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
        if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
            displayLinkSupported = TRUE;
    }
    return self;
}

OTHER TIPS

The cast you are making (EAGLView*) self.view isn't working. It thinks it is a UIView (probably because you don't say anywhere in the viewController that your self.view = myEAGLView;) and since UIView doesn't respond to setContext: you are getting the error. Note: i'm not too familiar with using openGL classes in general, but this seems like a more general error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top