I am having a problem that may be simple to fix, but not simple for me to debug. I simple have a button inside a view in IB; the file's owner is set to the view controller class I am using and when making the connections, everything seems fine, ie. the connector is finding the method I am trying to call etc.
however, I am receiving this error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIApplication getStarted:]: unrecognized selector sent to instance 0x3d19130'
My code is as follows:
RootViewController.h
#interface RootViewController : UIViewController {
IBOutlet UIButton* getStartedButton;
}
#property (nonatomic, retain) UIButton* getStartedButton;
- (IBAction) getStarted: (id)sender;
#end
RootViewController.m
#import "RootViewController.h"
#import "SimpleDrillDownAppDelegate.h"
#implementation RootViewController
#synthesize getStartedButton;
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction) getStarted: (id)sender {
NSLog(#"Button Tapped!");
//[self.view removeFromSuperview];
}
- (void)dealloc {
[getStartedButton release];
[super dealloc];
}
#end
Seems simple enough...any thoughs?
It looks like you have released the RootViewController after add it to your window.
Post here the piece of code where you add RootViewController to your window.
BTW, try to comment the line where you do the release. So, instead of use:
RootViewController *viewController = [[RootViewController alloc] init];
[window addSubview:viewController.view];
[viewController release];
Do it:
RootViewController *viewController = [[RootViewController alloc] init];
[window addSubview:viewController.view];
//[viewController release];
Your method "getStarted" should work after that.
Cheers,
VFN
You're sending getStarted to UIApplication and not RootViewController. Double check to make sure the button is hooked up properly to the view controller in Interface Builder. Your code looks fine.
I have the same problem, and finally found the answer at this forum post:
http://iphonedevbook.com/forum/viewtopic.php?f=25&t=706&start=0
When you instantiate your view controller class to be pushed into the navigation controller or similar, you have to make sure you instantiate it with your custom class name, and not UIViewController. This is easy to miss, and difficult to debug.
For example:
// this is wrong
RootViewController *viewController = [[UIViewController alloc] initWithNibName:#"TestView" bundle:nil];
// It should be
RootViewController *viewController = [[RootViewController alloc] initWithNibName:#"TestView" bundle:nil];
Hope it helps!
PS: Oops. Just noticed that your error says UIApplication, and not UIViewController, unlike mine. So probably like what Marc W said, somewhere you have used UIApplication where you should have used your custom class. It is probably something like my mistake.
Related
I have a project with one View. I'm drawing everything on it programically. So when i want to add another View (screen) to my project i create a class inherits from the UIViewController class and implements method
- (void)viewDidLoad
And then i want to load this View from my original View, and i do this:
In ViewController.h
#import <UIKit/UIKit.h>
#import "TestViewControllerClass.h"
#interface ViewController : UIViewController <UITableViewDataSource> {
}
#property (strong,nonatomic) TestViewControllerClass *testView;
#end
In ViewController.m
#implementation ViewController
#synthesize testView;
- (void)viewDidLoad
{
[super viewDidLoad];
testView = [[TestViewControllerClass alloc] init];
[self.view addSubview:testView]; //crash here
}
And then in my TestViewControllerClass.h
#import <UIKit/UIKit.h>
#interface TestViewControllerClass : UIViewController
#end
And TestViewControllerClass.m
- (void)viewDidLoad
{
[super viewDidLoad];
}
To check if method wiewDidLoad will be executed i put there a breakpoint, but nothing happend. In fact, my app crash (I put comment at code where).
When crashes i receive: -[TestViewControllerClass superview]: unrecognized selector sent to instance 0x683aca0
Replace
[self.view addSubview:testView]; //crash here
with
[self.view addSubview:testView.view];
Use this code...
[self.view addSubview:testView.view];
Hope,this will help you...
What you're doing is settings your ViewController as the view, not the real view
testView = [[TestViewControllerClass alloc] init];
[self.view addSubview:testView]; //crash here
this will obviously crash. Assuming you have a view variable declared in your header file called view, use
testView = [[TestViewControllerClass alloc] init];
[self.view addSubview:testView.view];
You can load two types for uiviewcontroller loading below:
[self.view addSubview:testView.view];
(or)
use presentmodalviewcontroller below code:
testView *popupView = [[testView alloc] initWithNibName:#"testView" bundle:nil];
popupView.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:popupView animated:YES];
dimiss modal view cntroller below code:
[self dismissModalViewControllerAnimated:YES];
thanks..!
I am trying to load a new view when I click a button in the app.
The error I am getting is -
View Switcher[6867:207] -[UIView pushViewController:animated:]: unrecognized selector sent to instance 0x6010660
and the source code snippet is -
-(IBAction) blueButtonPressed:(id)sender{
if(self.yellowViewController == nil){
YellowViewController *yellowController = [[YellowViewController alloc] initWithNibName:#"YellowView" bundle:nil];
self.yellowViewController = yellowController;
//[yellowController release];
//[self.view addSubview:yellowController.view];
//[self.view pushViewController:self.yellowViewController];
[self.navigationController pushViewController:self.yellowViewController];
[yellowController release];
}
//[self.navigationController pushViewController:self.yellowViewController animated:YES];
}
Here is the header file I am using -
#import <UIKit/UIKit.h>
#class BlueViewController;
#class YellowViewController;
#interface BlueViewController : UIViewController {
YellowViewController *yellowViewController;
BlueViewController *blueViewController;
}
-(IBAction)blueButtonPressed:(id)sender;
#property(retain) YellowViewController *yellowViewController;
#property(retain, nonatomic) BlueViewController *blueViewController;
#end
The link to the xcode project is - https://rapidshare.com/files/2403429896/View_Switcher.zip
pushViewController is a UINavigationController method.
[self.navigationController pushViewController:self.yellowViewController animated:YES];
I'm assuming you are in a UIViewController subclass
Could you post an Xcode project I need to see this.
Ok, I've look into your code, the problem is that you don't have any navigationController. Your app is structured like a view base application not like a navigation base application.
The result is that your self.navigationController == nil, that is why that call is ignored.
In your application delegate you need some code looking like this
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:switchViewController];
navCon.navigationBarHidden = YES;
self.window.rootViewController = navCon;
[window makeKeyAndVisible];
In the applicationFinised...
In your code, when you click on your switch in the toolbar, it's "working" because your using this code :
[blueViewController.view removeFromSuperview];
[self.view insertSubview:yellowViewController.view atIndex:0];
And there is no navigationController in that process.
You should use [self.view addSubview:yellowController.view];
Best to have a navigation controller where you push and pop controllers to or from.
UIView does not have pushViewController:animated: as a method.
You can push only in UINavigationController
I have an iPhone project that starts out with a standard UIView based Window... when the user clicks a button its suppose to launch into a new view with a UITabBarController -- similar to the way the iTunes Connect app behaves after you login. There are no sample code examples in the Apple documentation doing what I want but I know its possible because Apple has done it in their own apps (another example is the MobileMe iDisk app for iPhone).
I already tried the standard -presentModalViewController:animated: method and that did not work because there isn't a view that I can attach within the UITabBarController.
Next I am going to attempt to work with two window XIBs within the App Delegate to see if I can get that approach to work instead.
I would appreciate any insight if you know how to answer this little problem of mine. =)
What I ended up doing is this:
In my App Delegate, I have the following in my interface:
#interface myAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow * window;
LauncherViewController * startup;
UITabBarController * tabs;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet LauncherViewController * startup;
#property (nonatomic, retain) IBOutlet UITabBarController * tabs;
#end
In my implementation file, I add the following to the app start up function:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[self.window addSubview:self.startup.view];
[self.window makeKeyAndVisible];
NSNotificationCenter * notifier = [NSNotificationCenter defaultCenter];
[notifier addObserver:self
selector:#selector(launch)
name:MyAppLoginInitializedNotification
object:nil];
[notifier addObserver:self
selector:#selector(logout)
name:MyAppLogoutNotification
object:nil];
return YES;
}
- (void) launch {
[self.startup.view removeFromSuperview];
[self.window addSubview:tabs.view];
[self.window makeKeyWindow];
}
- (void) logout {
[self.tabs.view removeFromSuperview];
[self.window addSubview:startup.view];
[self.window makeKeyWindow];
}
My main XIB contains both the standard UIViewController defined as LauncherViewController as well as a generic UITabBarController. As soon as my main launcher controller authentices the user credentials and sends the MyAppLoginInitializedNotification, the app delegate switches from the launcher to the tab view enabling me to continue on with my app logic.
UITabBarController really is just a subclass of UIViewController, so -presentModalViewController:animated: should work:
UITabBarController *someController = [[UITabBarController alloc] init];
someController.viewControllers = /* your View Controllers here */
[self presentModalViewController:someController animated:NO];
if i understand your issue correctly, you want to start the UITabBarController View after the first view you mentioned in your Question, i am attaching a link doing the same thing you need except you have an Extra view before the UITabBarController View appears, hope it will give you a guide.
http://www.mobisoftinfotech.com/blog/iphone/iphone-tabbar-uitabbarcontroller-tutorial/
I don't think you have to re-add the UITabBarController in the nib file. Just create it in code, add it as the poster above says, and you should be good to go. Here's some code that works for me.
UITabBarController *nextController = [[UITabBarController alloc] init];
FirstController *firstView = [[FirstController alloc] initWithNibName:#"FirstView" bundle:nil];
SecondController *secondView = [[SecondController alloc] initWithNibName:#"SecondView" bundle:nil];
ThirdController *thirdView = [[ThirdController alloc] initWithNibName:#"ThirdView" bundle:nil];
[nextController setViewControllers:[NSArray arrayWithObjects:firstView, secondView, thirdView, nil] animated:NO];
Till this point it should be the same, but I'm pushing a tabbar controller into the uinavgiationcontroller instead, so this is where we might differ. I do it as follows:
[self.navigationController pushViewController:nextController animated:YES];
I'm using two UIViewController in Application Delegate and navigating to UIViewController using presentmodalviewcontroller. But Problem is that presentmodalviewcontroller works for first time UIViewController and when i want to navigate to second UIViewController using presentmodalviewcontroller then its showing first UIViewController.
The following is the code:-
-(void)removeTabBar:(NSString *)str
{
HelpViewController *hvc =[[HelpViewController alloc] initWithNibName:#"HelpViewController" bundle:[NSBundle mainBundle]];
VideoPlaylistViewController *vpvc =[[VideoPlaylistViewController alloc] initWithNibName:#"VideoPlaylistViewController" bundle:[NSBundle mainBundle]];
if ([str isEqualToString:#"Help"])
{
[tabBarController.view removeFromSuperview];
[vpvc dismissModalViewControllerAnimated:YES];
[viewController presentModalViewController:hvc animated:YES];
[hvc release];
}
if ([str isEqualToString:#"VideoPlaylist"])
{
[hvc dismissModalViewControllerAnimated:YES];
[viewController presentModalViewController:vpvc animated:YES];
[vpvc release];
}
}
Can Somebody help me in solving the problem?
You're making a new hvc and vpvc each time you run this function.
The first time through, I assume you call removeTabBar:#"Help", it makes a hvc and vpvc and then shows the correct one.
The second time you call it removeTabBar:#"VideoPlayList", you are making a new hvc and vpvc. This means that when you call hvc dismissModalViewController:YES]; you're not removing the one you added before, you're removing the new one that you just made which isn't being displayed at all!
To solve this you need to make your two controllers as properties in your app delegate and create them in the applicationDidFinishLaunching method.
Add these into your app delegate's .h file:
#class MyAppDelegate {
HelpViewController *hvc;
VideoPlaylistViewController *vpvc;
}
#property (nonatomic, retain) HelpViewController *hvc;
#property (nonatomic, retain) VideoPlaylistViewController *vpvc;
#end
and in your app delegate's .m file :
- (void)applicationDidFinishLaunching:(UIApplication *)application {
...
self.hvc = [[[HelpViewController alloc] initWithNibName:#"HelpViewController" bundle:nil] autorelease];
self.vpvc = [[[VideoPlaylistViewController alloc] initWithNibName:#"VideoPlaylistViewController" bundle:nil] autorelease];
...
}
and remove the first two lines in removeTabBar
I'm working on my first real iPhone app, a simple To-Do list application to help me organize stuff, except I'm getting an "unrecognized selector sent to instance 0x".
Specifically:
2010-02-20 14:30:09.200 ToDoApp[88562:20b] *** -[NSCFDictionary switchViews:]: unrecognized selector sent to instance 0x3d22de0
2010-02-20 14:30:09.201 ToDoApp[88562:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFDictionary switchViews:]: unrecognized selector sent to instance 0x3d22de0'
I've looked around and figured out that it might be a connection problem in IB, but I'm new to this whole connecting thing (man, I wish they supported Java or Python), so here's how it's laid out. I've got 3 classes, a SwitchViewController, a MainScreenViewController, and a ToDoListViewController. When I hit a button on MainScreenViewController, I trigger the "switchViews" function that's throwing this problem. They way I've got it set up is that the button (a UIBarButtonItem) has the "sentAction" go to switchViews. This ViewButton has its reference outlet as a IBOutlet in SwitchViewController.
So here's the .h for SVC:
#import <UIKit/UIKit.h>
#class MainScreenViewController;
#class ToDoListViewController;
#class EditViewController;
#define kMinimumGestureLength 25
#define kMaximumVariance 5
#interface SwitchViewController : UIViewController {
MainScreenViewController *mainScreenViewController;
ToDoListViewController *toDoListViewController;
EditViewController *editViewController;
IBOutlet UIBarButtonItem *viewButton;
CGPoint gestureStartPoint;
}
#property (retain, nonatomic) MainScreenViewController *mainScreenViewController;
#property (retain, nonatomic) ToDoListViewController *toDoListViewController;
#property (retain, nonatomic) EditViewController *editViewController;
#property (retain, nonatomic) IBOutlet UIBarButtonItem *viewButton;
#property CGPoint gestureStartPoint;
-(IBAction)switchViews:(id)sender;
And for the switchViews function:
-(IBAction) switchViews:(id)sender
{
NSLog(#"Switching views");
if(self.toDoListViewController.view.superview == nil){
if(self.toDoListViewController ==nil){
ToDoListViewController *toDoVC = [[ToDoListViewController alloc] initWithNibName:#"ToDoListView" bundle:nil];
self.toDoListViewController = toDoVC;
//[toDoVC release];
}
[mainScreenViewController.view removeFromSuperview];
[self.view insertSubview:toDoListViewController.view atIndex:0];
}
else{
if(self.mainScreenViewController == nil){
MainScreenViewController *mainController = [[MainScreenViewController alloc] initWithNibName:#"MainScreenView" bundle:nil];
self.mainScreenViewController = mainController;
//[mainController release];
}
[toDoListViewController.view removeFromSuperview];
[self.view insertSubview:mainScreenViewController.view atIndex:0];
}
}
So in short, I'm totally lost, and this is really frustrating. Anyone have any advice, or need any more code?
We just ran into the same problem. It seems we released the ViewController object in the AppDelegate and then our nib view tried to invoke an IBAction (on the view controller). Half the time we were getting "EXC_BAD_ACCESS" (aka messaging a released object), and half the time we were getting "unrecognized selector sent to instance" of NSCFString, NSCFArray, all sorts of things (aka messaging an area of memory now taken up by a different object).
Just check your ViewController hasn't been released.
Okay, got the solution pointed out to me. Should have had it routed through FirstResponder (I ... really don't understand why that works, but at this point I'm just happy it works.)
I'm not sure how first responder works anyways (none of the books I have really mention it), but it... works? If someone wants to give me a rundown, that'd be useful... but this question has been answered.
I'm going to guess the problem is in your nib file.
The error means that upon clicking the button, the button tries to send a message/method-call of switchView to an NSDictionary object which of course has no such method. The error then lays in where the buttons action is pointed.
Check the nib for this view. Look at the File Owner and check the class assigned to it. Make sure it is SwitchViewController and not a dictionary for some reason. If the File Owner property is set to a dictionary class it will load a dictionary and try to send the action method it to it.
The right answer is this:
The view controller that we assign as the first screen in the app delegate shouldn't be released in the - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method. In your case the first screen is MainScreenViewController.
It (MainScreenViewController instance)should be released in app delegate's dealloc method.
- (void)dealloc
{
[_window release];
[mainScreenViewController release];
[super dealloc];
}
This might also help. The Analyzer routine recommended I release a few objects, and I did. Turns out, I needed those objects in the app. In the xAppDelegate.m file (or whatever) in the appDidFinishLaunching method/message/function/routine/thing, use
UINavigationController *navController = [[UINavigationController alloc] init];
instead of
UINavigationController *navController = [[[UINavigationController alloc] init] autorelease];
Also, Analyzer recommended I release the object I pushed onto the nav controller. Big mistake. That file was my menu screen and when I pressed a button, I received a unrecognized selector sent to instance. Apparently, it was calling IBAction on NSString and NSDictionary, which is not good.
FYI I was getting this when using ARC and the xib was being loading and put onto the screen, but somehow the VC itself was not being retained.
I solved it by adding a variable to store reference in the VC that was presenting it.
The problem is, you have initiated the UIViewController instance as a method variable. So the view controller have no scope after the execution of the method and so it is released from the memory cycle. So you have to make your view controller instance as class level.
#interface SwitchViewController () {
ToDoListViewController *toDoVC;
MainScreenViewController *mainController;
}
-(IBAction) switchViews:(id)sender
{
if (!toDoVC)
toDoVC = [[ToDoListViewController alloc] initWithNibName:#"ToDoListView" bundle:nil];
if (!mainController)
mainController = [[MainScreenViewController alloc] initWithNibName:#"MainScreenView" bundle:nil];
//Your stuff with the view controllers...
}