1

Hey guys I'm trying to get my app to load a new view when a certain method is called. Inside the method I have the code:

 ViewController *GameOverViewController = [[ViewController alloc] init];
 [self presentViewController:GameOverViewController animated:YES completion:nil];

which is taken straight from How to switch views programmatically in a ViewController? (XCode iPhone).

Anyways, when I try to switch from my view controller called Game to a view controller called GameOverViewController I just get a ton of errors. Mainly

"Unknown receiver 'ViewController'; did you mean 'UIViewController'

And my app crashes. I'm obviously doing something wrong but I have no idea what that is exactly. Do I have to declare the GameOverViewController in my Game.h or in my appDelegate or something?

EDIT: Both view controllers are in the same main.Storyboard file if that matters

Community
  • 1
  • 1
Pecans
  • 153
  • 1
  • 12
  • I'm using storyboards – Pecans Oct 29 '14 at 04:23
  • Then either (a) give your next scene a unique storyboard id that you reference in `instantiateViewControllerWithIdentifier` or (b) have a segue between the two scenes, give that segue a unique storyboard id, and then call `performSegueWithIdentifier`. See my answer below. Even if you got the right class name, the `[[ViewController alloc] init]` technique wasn't going to work for you. – Rob Oct 29 '14 at 04:32
  • what is `ViewController`? – holex Oct 29 '14 at 17:11

2 Answers2

3

The unknown receiver message means that it can't find the class definition for the view controller class called ViewController. Is that really the name of the class you're using for your "game over" view controller? And if so, have you done the #import "ViewController.h" at the start of this .m file?

The fundamental problem is that it cannot find the class called ViewController.


Setting that aside, we don't generally instantiate new view controllers using alloc and init anymore, as that answer may have implied. That was a technique used with NIBs (and only worked if the NIB name matched the class name).

For new developers, I might encourage you to start with storyboards. Any modern tutorial should walk you through how to use storyboards. (Google "iOS storyboard tutorial" and you'll probably get lots of hits.)

If, for example, your storyboard has a scene with a "storyboard identifier" of GameOverViewController, then you might programmatically instantiate it and present it with something like:

UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"GameOverViewController"];
[self presentViewController:controller animated:YES completion:nil];

Or, if your storyboard had a segue from the current scene to the next scene, you'd make sure that segue had its own storyboard identifier, e.g. GameOverSegue, and then you'd perform it like so:

[self performSegueWithIdentifier:@"GameOverSegue" sender:self];

But find yourself a good introduction/tutorial on storyboards, as stumbling through Stack Overflow for answers will not be a very fruitful exercise.


For historical purposes, it's worth noting that if you were using NIBs, you can use the construct you referenced to in your question (but you'd have to make sure that (a) the class name was right; and (b) you did the #import that class header). And if the destination NIB had a different name than the class, you'd have to do something like:

UIViewController *controller = [[NSBundle mainBundle] loadNibNamed:@"nibname" owner:self options:nil]`;
[self presentViewController:controller animated:YES completion:nil];

But this is all academic unless you're using NIBs. If using storyboards, use one of the above patterns if you need to transition to a new scene programmatically.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • "you generally don't just instantiate the view controller that way." Good point. In addition to your suggested ways of loading a view controller, if you're using XIB files you might use `initWithNibName:bundle:` to load a view controller from an XIB. – Duncan C Oct 29 '14 at 02:02
  • Agreed. Actually, if the NIB name matched the class name, you actually could get away with `alloc`/`init` and it would do the NIB stuff for you. But the `initWithNibName` was a more robust way of doing it in those cases where the NIB name differed. But I'd be surprised if he's using NIBs at all, so it's probably academic. lol. – Rob Oct 29 '14 at 02:20
  • Thanks! This combined with your comment above solved it for me! This is for academic purposes btw :) – Pecans Oct 30 '14 at 03:45
0

You are in over your head. You should slow down and do some more studying or things are going to crash all over the place. I suggest going through a good book on iOS development and doing the exercises.

On to your question:

In the code you posted you're using a class "ViewController". There is no system-defined class "ViewController", although it is a common class name in example projects, and I think some of the project templates in Xcode even create a root view controller with that class name.

The name you give to your variable ("GameOverViewController" in the code above) is local and not really important. That's just a variable name. You can rename it lateForDinner if you want to, and it won't make any difference as long as you change that name everywhere in the scope in which it's defined.

The fact that you're being told that the class "ViewController" is unknown suggests that it hasn't been defined anywhere in your program.

You need an @interface and @implementation section that defines the ViewController class. Usually those will be in files called ViewController.h and ViewController.m, respectively. They might look something like this:

//ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController: UIViewController //Defines it as a subclass of UIViewController

// properties and methods of ViewController defined here

@end

And the .m file:

//ViewController.m


@implementation ViewController

// Implementation of ViewController methods go here.

@end

It's also possible to include the interfaces of multiple classes in a single header file, and the implementations of multiple classes in a single .m file, although I dislike this practice intensely. Keep it simple - one class per .h/.m file pair, with the file names identical to the class name.

Duncan C
  • 128,072
  • 22
  • 173
  • 272