Basically I want to get a list of action targets for a UIButton. I have gone through this and my question is slightly different because I do not know what the target is. All I have is a UIButton object. So here's what I did to capture all action targets.
Inspired by below method which works where I get firstResponder object as valid pointer.
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView *firstResponder = [keyWindow performSelector:#selector(firstResponder)];
I used class-dump on UIKit to see UIWindow class and I found firstResponder as below.
NS_CLASS_AVAILABLE_IOS(2_0) #interface UIWindow : UIView {
#package
UIResponder *_firstResponder;
}
Then I checked UIControl which via class-dump as
NS_CLASS_AVAILABLE_IOS(2_0) #interface UIControl : UIView {
#package
NSMutableArray* _targetActions;
}
So here's what I try to do and it crashes.
NSMutableArray *arr = (NSMutableArray*)[((UIControl*)btn) performSelector:#selector(targetActions)];
NSLog(#"%#",arr);
Sounds like conspiracy against me. But more likely I am goofing up some thing. Does any know how to access targetActions Array of UIControl?
EDIT: Here's the error message -
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '- [UIRoundedRectButton targetActions]: unrecognized selector sent to instance 0x1c0ab0'
Any help appreciated.
According to the UIControl documentation, the message to send to get a list of targets is allTargets not targetActions as you suggest. The rest of the solution is in the accepted answer to How to get UIButton Target, Action and Control events?
A debugging technique you can use when you don't know what you're doing is to use respondsToSelector to check whether you're sending a message that the object can respond to:
when to use respondsToSelector in objective-c
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];
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
Having read this thread, I'm trying to insert a link to an external web page calling an action upon touch inside on a button (button created in storyboard with xCode 4.6).
This is the action:
-(IBAction)outLink:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: #"https://www.mysite.com/index.php"]];
}
and this the header file (.h):
#interface MenuViewController : UIViewController <UITableViewDataSource, UITabBarControllerDelegate>{
IBOutlet UIButton *linkToSite;
}
-(IBAction)outLink;
I have linked the button to the element in the storyboard, and I've linked the action to the Touch Up Inside event, but I get this error when I click in the simulator on the button:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MenuViewController outLink]: unrecognized selector sent to instance 0x717d340'
Change method name in .h class and reconnect your outlet for touchupinside event.
-(IBAction)outLink:(id)sender;
Hope it helps you.
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.