I'm making a simple calculator and when I use the addition button, the iOS Simulator crashes and I get an NSInvalidArgumentException. What do I do to prevent this from happening?
Error Report:
2013-06-23 17:18:54.574 Tutorial Test (Storyboard)[9744:c07] -[ViewController2 addition]:
unrecognized selector sent to instance 0x75858f0
2013-06-23 17:18:54.577 Tutorial Test (Storyboard)[9744:c07] *** Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '-[ViewController2 addition]:
unrecognized selector sent to instance 0x75858f0'
*** First throw call stack:
(0x1c91012 0x10cee7e 0x1d1c4bd 0x1c80bbc 0x1c8094e 0x10e2705 0x162c0 0x16258 0xd7021
0xd757f 0xd66e8 0x45cef 0x45f02 0x23d4a 0x15698 0x1becdf9 0x1becad0 0x1c06bf5 0x1c06962
0x1c37bb6 0x1c36f44 0x1c36e1b 0x1beb7e3 0x1beb668 0x12ffc 0x1e2d 0x1d55)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Code in ViewController that has this error:
View Controller.h
#import <UIKit/UIKit.h>
//Calculator
#interface ViewController2 : UIViewController{
IBOutlet UITextField *textField1;
IBOutlet UITextField *textField2;
IBOutlet UILabel *label;
}
-(IBAction)addition;
-(IBAction)subtract;
-(IBAction)multiply;
-(IBAction)divide;
-(IBAction)clear;
#end
View Controller.m
//Addition
-(IBAction)plus
{
float a = ([textField1.text floatValue]);
float b = a+([textField2.text floatValue]);
label.text = [[NSString alloc] initWithFormat:#"%2.f", b];
}
You named the method in the .m file plus, rather than addition. That is why the method addition isn't found, and the fix would be to rename the method in the .m file from plus to addition:
//Addition
-(IBAction)addition
{
float a = [textField1.text floatValue];
float b = [textField2.text floatValue];
label.text = [[NSString alloc] initWithFormat:#"%2.f", a+b];
}
Have you allocated an instance of the ViewController2 class?
For example:
ViewController2 *vc2 = [[ViewController2 alloc] init];
[vc2 addition];
Also, if the .m code you posted is the full contents of that file, then you're also missing
-(IBAction)addition {
...
}
You didn't inplement the right method.
You call addition but you never actually implement it. Declaring the method signature in the .h is not enough, you have to code the method.
This means that the selector that you are calling is not available on the class you called it against. The best thing to do is place a breakpoint where the method is being called. Go to the debugger and po your object.
po 0x75858f0
in this instance. However that number could be an object and it could be different. Look at the number in the console.
Make sure the object is of the proper class. Then check that class to make sure it responds to the selector you are calling.
Edit: Your problem is that your plus method should be renamed to addition. The names in the .h must match the names in the .m
Related
I am new to using this method so I could be doing this completely wrong so here is my code:
#property (nonatomic, weak) ConverterViewController *converterViewController;
#property (nonatomic, weak) CalculatorViewController *calculatorViewController;
If I am understanding this code correctly, these are acting as references to Two different ViewControllers.
Then I have this in my viewDidAppear method:
[self addChildViewController:_converterViewController];
[_converterViewController didMoveToParentViewController:self];
[self.view addSubview:_converterViewController.view];
I am getting an NSException at the first line when I try and add it as a child view controller. So not knowing whether or not this should then call some methods in my ConverterViewController class I put some breakpoints within that class both the initWithNibName and viewDidLoad methods and I found that neither of these methods are being called, so Im not exactly sure what is wrong. Then again Im not really sure what could go wrong so any help is greatly appreciated.
This is all I get from the console:
libc++abi.dylib: terminating with uncaught exception of type NSException
Updated Answer:
[self addChildViewController:_converterViewController]; does not create the converterViewController.
It simply takes the converterViewController object and adds it as a childViewController to self.
You will need to allocate memory and instantiate the object converterViewController before -addChildViewController: or else it's value will be nil and nothing will happen.
So... something this:
_converterViewController = [[ConverterViewController alloc] initWithNibName:#"ConverterViewController"
bundle:nil];
//now... adding it as childViewController should work
[self addChildViewController:_converterViewController];
[_converterViewController didMoveToParentViewController:self];
//optional: give it a frame explicitly so you may arrange more childViewControllers
//[_converterViewController.view setFrame:CGRectMake(0,0,100,100)];
[self.view addSubview:_converterViewController.view];
What I have:
four TableViewController(A, B, C, D) - which would show four category
of content.
fake TabBarController based on UITabBarController, it
works fine.
What I want to do:
Add a button on ATableView, and it will use a method on my FakeTabBarController (because I want to share the method so I can use it on BTableViewController, CTableViewController rather than duplicate it two or three times)
So I just make the method public (on the .h file), and included the .h file in my ATableViewController. Then,
addTarget:action:forControlEvents: as always, but.. it doesn't work, please help!
Error:
[ATableViewController assisitantButtonPressed:]: unrecognized selector sent to instance 0x715a8d0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ATableViewController assisitantButtonPressed:]: unrecognized selector sent to instance 0x715a8d0'
*** First throw call stack:
(0x1ca1012 0x10dee7e 0x1d2c4bd 0x1c90bbc 0x1c9094e 0x10f2705 0x262c0 0x26258 0xe7021 0xe757f 0xe66e8 0x2ea1d3 0x1c69afe 0x1c69a3d 0x1c477c2 0x1c46f44 0x1c46e1b 0x1bfb7e3 0x1bfb668 0x22ffc 0x1c8d 0x1bb5)
libc++abi.dylib: terminate called throwing an exception
FakeTabBarController.h:
#import <UIKit/UIKit.h>
#interface CustomTabBarController : UITabBarController
- (IBAction)assisitantButtonPressed:(UIButton *)sender;
#end
FakeTabBarController.m:
...
- (IBAction)assisitantButtonPressed:(UIButton *)sender
{
switch ([sender tag]) {
case 0: // AA
NSLog(#"AA");
break;
case 1: // BB
NSLog(#"BB");
break;
default:
break;
}
}
...
ATableViewController.m:
#import "ATableViewController.h"
#import "ATableCell.h"
#import "FakeTabBarController.h"
...
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage *AAImage = [UIImage imageNamed:#"search.png"];
UIButton *AAButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width * 0.73, 0, AAImage.size.width, AAImage.size.height)];
[AAButton setTag:0];
[AAButton setImage:searchImage forState:UIControlStateNormal];
[AAButton addTarget:self action:#selector(assisitantButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:AAButton];
}
This line
[AAButton addTarget:self action:#selector(assisitantButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
sets the target to method assisitantButtonPressed: of self, which is ATableViewController. It throws exception because ATableViewController doesn't have that method. The correct way is to add a weak property to ATableViewController to keep a reference to CustomTabBarController and addTarget to that TabBar, rather than self
#interface ATableViewController
#property (weak, nonatomic) CustomTabBarController* tabBar;
...
#end
#implementation ATableViewController
-(void)viewDidLoad {
[super viewDidLoad];
self.tabBar = <you must somehow obtain the tab bar reference, either here or in init>
...
[AAButton addTarget:self.tabBar action:#selector(assisitantButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
...
}
#end
It's good that you're trying to avoid code duplication. However since ATableViewController, BTableViewController, ... are very similar (judging from your question and their naming), you may want to use just one single TableViewController but with different actual data. Besides, if the method assisitantButtonPressed: really belongs to the table view controller and you moved it to the navBar just to avoid code duplication, it is a very bad practice.
I'm getting an unrecognized selector exception trying to set the alpha on a UIImageView, but I don't understand why this should be seeing a UIImageView inherits from UIView and alpha is a property of that.
#property (strong, nonatomic) IBOutlet UIImageView *pulldownTab;
...
self.pulldownTab.alpha = 1.0;
2013-05-21 07:33:32.964 TestControl[655:907] -[__NSCFNumber setAlpha:]: unrecognized selector sent to instance 0x1e587fa0
** UPDATE **
Moral of the story - Solved. be careful with key value coding, a call to this function was being made earlier
- (void) fadeToAlphaValue: (double) alpha forKeyPath: (NSString*) keyPath
{
NSNumber* number = [NSNumber numberWithDouble:alpha];
[UIView animateWithDuration:kFadeAnimationDuration
animations:^ {
[self setValue:number forKeyPath:keyPath];
}];
}
[self fadeToAlphaValue:0.0 forKeyPath:#"self.pulldownTab"];
Are you sure you are assigning the IBOutlet properly in the interface Builder?
The reference is not properly working, when you access to self.pulldownTab is accessing to a NSCFNumber variable in memory.
I had the same problem here. In my case, I was setting myTextView, but not the .text property, earlier in the code, like this:
self.myTextView = #"text";
instead of what I should have been doing:
self.myTextView.text = #"text";
for some reason this didn't throw any errors at this point, but it created an issue later when I tried to set the alpha property on an NSString (which doesn't have such a thing) :)
Anyways, just look for any stupid mistakes like this in your code before the .alpha property is being set - they'll likely be the cause of the problem!
I created a static library for use in my other iOS application projects. The way it works is the application project implements the protocol in my static library and calls a method in the static library. Then the static library presents a view on top of the calling view. Here's how the code is:
MyFile.h file of the main class in delegate:
#protocol MyHandlerDelegate <NSObject>
- (void)infoRetrieved:(BOOL)success;
#end
#interface MyFile : UIViewController
{
id <MyHandlerDelegate> delegate;
}
#property (retain) id delegate;
MyFile.m contains:
- (void)showRewards
{
[[[self delegate] view] addSubview:view1];
}
Now when I created a dummy application with just a single button, this worked fine and the static library successfully presented a view on top of the calling view.
Now I need to make this work in an open source game TweetJump (built on Cocos2D). In the highscores class, I have included the header file and implemented the delegate. In the implementation file, I call the following code:
MyFile *mf = [[MyFile alloc] init];
[mf setDelegate:self];
[mf showRewards];
For your consideration, I have hosted the Highscore class - Header and Implementation. The error that I am getting when the above method is executed is:
2013-04-16 23:54:42.658 tweejump[11502:c07] +[Highscore view]: unrecognized selector sent to class 0xecc08
2013-04-16 23:54:42.661 tweejump[11502:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[Highscore view]: unrecognized selector sent to class 0xecc08'
I know its a tedious question. Will greatly appreciate the help. Thanks
It's telling you that Highscore class does not have a view method. You protocol says the delegate only has to be an NSObject nothing more specific.
It looks like you're calling this code in a class method rather than an instance method. An object is not interchangeable with its class. Have your actual Highscore object do this instead of the class.
I have an UIViewController with several subviews in its view property (UISearchbar and several UIButtons). The UIButtons hooked up to typical IBActions like -(IBAction)buttonPressed:(id)sender for the UIControlEventTouchUpInside state - it doesn't matter if I do it in IB or programmatically.
- (void)viewDidLoad {
MUZTitleViewController *title = [[MUZTitleViewController alloc]
initWithNibName:nil bundle:nil];
self.navigationItem.titleView = title.view;
}
In my project there's also an UINavigationController. When I set the navigationItem.titleView of the UINavigationBar to the view of my UIViewControllers view I get an EXC_BAD_ACCESS exception, as soon as I tap one of the button. I don't know why this is.
I uploaded a small sample project to illustrate my problem: Test010.xcodeproj (it's ARC enabled)
More and more I come to the conclusion that it's not a good idea to use the UIViewControllers view and assign it to the titleView but I don't see any alternative here.
Edit: Sorry, the sample project commented out the call which causes the exception. I reuploaded the linked project file.
Edit^2: As PengOne pointed out I've skipped the exact error message I got:
2011-09-10 23:09:50.621 Test010[78639:f803] -[CALayer buttonPressed:]: unrecognized selector sent to instance 0x9254ae0
2011-09-10 23:09:50.623 Test010[78639:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CALayer buttonPressed:]: unrecognized selector sent to instance 0x9254ae0'
Have you tried setting NSZombieEnabled to YES? If I do this, the console shows the following output:
2011-09-10 22:56:23.329 Test010[6481:ef03] *** -[MUZTitleViewController
performSelector:withObject:withObject:]: message sent to deallocated
instance 0x7a7ff70
As the project is ARC enabled, the controller seems to get deallocated some time after this line:
MUZTitleViewController *title = [[MUZTitleViewController alloc] initWithNibName:nil bundle:nil];
I am not sure what the best solution is, but a property definitely helps to prevent the exception like so:
// MUZDetailViewController.h
#property (strong, nonatomic) MUZTitleViewController *title;
// MUZDetailViewController.m
#synthesize title;
self.title = [[MUZTitleViewController alloc] initWithNibName:nil bundle:nil];
self.navigationItem.titleView = title.view;
The problem that you were having with ARC can also be resolved by setting the initial view controller of your application as your main window's rootViewController property instead of using addSubview.
Doing this avoids the need to add each custom view controller as a property.