Let's say that I want to create a GestureRecognizer object and have my whole logic in there. So when I add the NSObject as target for my recogniser:
initWithTarget:self action:#selector(doTheRecognizerThing:)
I'm facing an issue and I'm not sure why. I get an
unrecognized selector sent to instance
error although the doTheRecognizerThing method is properly implemented in my NSObject.
If I add the target and implement the method in any other object such as UIView or UIViewController I don't get any issues. Is there an explanation for that?
EDIT
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self
action:#selector(doTheRecognizerThing:)];
Implemantation
- (void) doTheRecognizerThing:(UIPanGestureRecognizer *)panGestureRecognizer {
//blah blah blah
}
Error Message:
-[CALayerArray doTheRecognizerThing:]: unrecognized selector sent to instance 0x14648a80
2015-01-06 23:05:20.788 Gestures[2203:1094298] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CALayerArray doTheRecognizerThing:]: unrecognized selector sent to instance 0x14648a80'
At one point you will add the recognizer to a view. This holds the recognizer strongly. At some point your object goes away, while the view stays – and with it the recognizer. That calls the method, but the object is gone and replaced by something else.
Try this:
initWithTarget:ObjectWithThatMethod action:#selector(doTheRecognizerThing:)
make sure doTheRecognizerThing is in header file.
And make sure that NSObject is not nil.
Related
I've a really strange error, and I cannot find the problem.
In my iPad APP I've a UINavigationController, a UITableViewController as master and a UIViewController containing a UIWebView as detail.
I launch the APP, the UITableViewController is shown. By segue I open the detail as usual. Then I have a back button in my detailviewcontroller that calls this method
[self.contentWebView setDelegate:nil];
[self.contentWebView stopLoading];
[self.navigationController popViewControllerAnimated:YES];
It gets poped and the master is shown again. Its
- (void)viewWillAppear:(BOOL)animated
gets called, but then I get the following error:
2014-06-06 15:56:58.156 Knowledge[356:60b] -[_UIWebViewScrollViewDelegateForwarder scrollViewWasRemoved:]: unrecognized selector sent to instance 0x170429f60
2014-06-06 15:56:58.159 Knowledge[356:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_UIWebViewScrollViewDelegateForwarder scrollViewWasRemoved:]: unrecognized selector sent to instance 0x170429f60'
*** First throw call stack:
(0x189582f50 [...] 0x196553aa0)
libc++abi.dylib: terminating with uncaught exception of type NSException
BUT, this happens only on the iPad Air... older iPads work as expected
UPDATE:
I added now the command [self.contentWebView removeFromSuperview]; after "stopLoading" and now the error is happing right up there.
Please ignore this answer if you are not touching scroll view's (of the web view) delegate reference.
I was facing the same strange error. After some investigation, I found that it was happening because scroll view's (of the web view) delegate was altered in controller's viewDidLoad method:
[self webView].scrollView.delegate = self;
In some cases, scroll view invokes delegate method(s) even after your view controller is destroyed. This should be prevented by weak delegate reference, but for some reason scroll view calls delegate method on deallocated (zombie) object anyway. I assume this is a bug in the framework.
So here what you can do: set delegate reference to nil in your controller's dealloc method:
- (void)dealloc
{
[self webView].scrollView.delegate = nil;
}
After deallocation, scroll view will be prevented from calling any method on no longer existing controller.
There are so many cases for "Unrecognized Selector Sent To Instance", I don't think I will find mine in so many threads. Or if I do it will take a month or so.
To be short. I receive this error, and my situation is:
I have a table view displaying recipes that are fetched from Core Data. When segue fires, it gets destination controller (which is UITabBarController), and provides a recipe for it.
The code for the segue method is:
if ([segue.identifier isEqualToString:#"RecipeTabBarController"]) {
RecipeTabBarController *VC = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Recipe *recipe = (Recipe*)[_controller objectAtIndexPath:indexPath];
VC.recipe = recipe;
}
TabBarController (which is the VC) has a property of a recipe, like so:
#property (nonatomic, strong) Recipe *recipe;
When I tap the cell, the segue fires, and the error occurs, with the following message from console:
2013-09-25 18:55:21.888 RecipeBank [974:60b] -[UITabBarController setRecipe:]: unrecognized selector sent to instance 0x15da8280
2013-09-25 18:55:21.892 RecipeBank [974:60b] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITabBarController setRecipe:]: unrecognized selector sent to instance 0x15da8280'
First throw call stack:
(0x30583f53 0x3abec6af 0x305878e7 0x305861d3 0x304d5598 0x6676f 0x3319f6f1 0x665b7 0x32e1232b 0x32ec5253 0x32d75971 0x32ced473 0x3054f1d5 0x3054cb79 0x3054cebb 0x304b7ce7 0x304b7acb 0x35185283 0x32d59a41 0x67711 0x3b0f4ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
RecipeTabBarController imports Recipe class in header and TableViewController that's performing segue imports RecipeTabBarController for it as well. So no mistake there.
What could be wrong?
Please help. Thanks.
Sounds like the class of the destination view controller is UITabBarController and not your own class RecipeTabBarController. Look in your storyboard as to how you have the segue set up and figure out why things are not what you expect.
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
I need to create a number of UIScrollViews dynamically and fill them with content. This is all good except when i set the delegate to self and pan the list i get this exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString scrollViewDidScroll:]: unrecognized selector sent to instance 0x7581230'
NSCFString obviously isn't my view controller (which implements the protocol UIScrollViewDelegate) so from what i gather somehow the memory gets messed up and it doesn't keep the reference correctly. Occasionally this can be something else too which strongly points to something being wrong with the memory
Here's the code to create the list:
for (NSUInteger i = 0; i < self.stories.currentStory.selectableWordCount; i++) {
UIScrollView *list = [[UIScrollView alloc] init];
list.alwaysBounceVertical = YES;
list.showsVerticalScrollIndicator = NO;
list.clipsToBounds = NO;
list.delegate = self;
list.pagingEnabled = YES;
[self.view addSubview:list];
.. // add UILabels to the list, set the frame, contentSize etc
[self.wordLists addObject:list]; // this is a #property (nonatomic, strong) NSMutableArray, declared in a private interface()
}
If i NSLog the delegate it's correct. respondsToSelector also matches fine. Interestingly if i comment out the scrollViewDidScroll: respondsToSelector: doesn't match any more and (probably because of this) the UIScrollView won't attempt to call this method any more. This then means that it can reach the delegate correctly to check for the method availability but when it gets called something goes wrong.
I'm targeting iOS5 with ARC. If this wasn't the case i would assume that i messed something up with the memory myself but now i don't have the same control.
I'm having a hard time debugging this issue, any help on how to proceed would be appreciated
D'uh. I was obviously looking in the wrong place. The view controller was added through a .xib and the view was pointing to a subview on the stage. However i needed to create an IBOutlet to the view controller in the main view controller to make sure it stays in memory. Hopefully this can help somebody else with a similar problem :)
I have a strange issue with UIGestureRecognizer
I've create a class where i declare the gesture recognizer, and put self as a target
-(id)initWithTextView:(UITextView*)theTextView withDelegate:(id<WordSelectionDelegate>)theDelegate
{
if (self = [super init])
{
delegate = theDelegate;
textView = theTextView;
// init long press gesture to detect pressing on text elements
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPressFromSender:)];
[textView addGestureRecognizer:longPressGesture];
}
return self;
}
But the trick is when i actually make a long press gesture i have next error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMutableAttributedString handleLongPressFromSender:]: unrecognized selector sent to instance 0x76227b0'
Why does the messages to self goes to String???
By the way, the problem is undoubtedly that the object that has the handleLongPressFromSender instance method (i.e. the object you're initializing with initWithTextView) is falling out of scope by the time the UILongPressGestureRecognizer is invoked. You need to check the the scope of that object.
For example, assuming that the name of this class was MyTextViewHandler, imagine you had a viewDidLoad for some view controller that had something like:
- (void)viewDidLoad
{
[super viewDidLoad];
// do a bunch of initialization
MyTextViewHandler *textViewDelegate = [[MyTextViewHandler alloc] initWithTextView:self.textview withDelegate:self];
}
If you did something like that in ARC project, you'd get the crash you describe (because the textViewDelegate object was a local object of viewDidLoad and will fall out of scope at the end of that method). If you make this delegate handler class an instance variable (or property) of your view controller, then this problem goes away.