Creating member object in Xcode: Program received signal: "SIGABRT" - objective-c

Warning: complete newbie Xcode question.
In MainViewController.h I have the following line:
IBOutlet WorkItem *m_WIone;
I have created a class called WorkItem which is inherited from UILabel. The line above is so that I can use m_WIone (which will eventually become an array of such objects) as a member variable throughout MainViewController.
I have tried various ways to call WorkItem methods and finally settled on:
[m_WIone Reset];
where Reset is a WorkItem method. The method is declared in WorkItem.h as:
-(void) Reset;
and in WorkItem.m as:
-(void) Reset {}
With or without contents in this method, the app always crashes with:
Thread 1: Program received signal: "SIGABRT".
In the logging, I read:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILabel Reset]: unrecognized selector sent to instance 0x6a5f9f0'
How can I solve this? Am I even declaring this member variable correctly? (Despite trawling through StackOverflow, I cannot find the solution.)

Did you specify your custom class for the NIB? It seems like you want a widget in XCode's Interface Builder to use your custom class. Only the default class (UILabel) would be instantiated instead of your custom class.
Click on the UILabel you're using as the outlet and change the class (the screenshot here is for UITableView, but it should work the same for UILabel).
With that being said, there are alternatives to what you're trying to do. Instead of just using UILabel (which you eventually plan to make an array of them). Why not use a UITableView and customize cells to what you see fit (since UITableViews optimal for displaying lists of items)?

Related

Unrecognized Selector Sent to Instance; selector doesn't exist?

So I'm new to objective c, practically new to programming in general.
Anyway, in my simple program, I control-dragged my UITextField from the storyboard into my ViewController.m thinking it was a way to create a method to be invoked when the field was entered/tapped on. It wasn't long until I deleted the method.
When running the simulator, the keyboard would come up and the text field would already be focused on. If I tapped anywhere else on the screen, it resulted in a crash giving me the unrecognized selector error for the selector I already deleted.
There's nothing in my ViewController.h and the rest of the code seems fine. If I re-add the selector with no instructions, it behaves as intended and the keyboard resigns. My question is, why am I getting this error?
It would be more helpful to have the output of the crash. With that said I suspect your storyboard still has an outlet hooked up, referencing the function or outlet you created. From your storyboard click on your textfield and then navigate to the connections inspector (view -> utilities -> connections inspector). From there you should be able to see any connections you have made. Click the x to get rid of it.
The connection inspector is the icon in the upper right with the right facing arrow inside of a circle.
Edit:
I realized you asked why this is happening and not how to fix it. Unrecognized selector means just what it sounds like. Your code, in this case the storyboard is trying to call a method or access a variable on an object that doesn't implement that method. Normally the compiler catches these types of errors in your code but there are cases it can't catch, like the one your experiencing. For example it is ok to assign an NSArray object to a variable declared as something else, say an NSString as follows
id object = #[#"hello", #"world"];
NSString *notAString = object;
[notAString length];
Try running this and it will crash with a similar error because NSArray implement the length method, or in Objective-c speak, it doesn't respond to the selector "length".
Most typically it's this:
Select your UITextField in IB, go to the Connections inspector and remove the ghost connection to the removed method.

What is the correct way to handle an error in awakeFromNib?

In my main application (MyApp) I programmatically create other windows by creating new instances of a window controller (MyWindowController). When the window controller is initialised, it loads a window and other views/objects from a nib file by calling [self.window makeKeyWindow]. In the awakeFromNib method on one of these objects (MyModel), there is some code that may fail (due to name resolution), and I would like to display an error to the user, and destroy the window controller, the window, and all related objects.
In summary:
Application creates new instance of MyWindowController.
MyWindowController loads a window and other views/objects from a nib file by calling [self.window makeKeyWindow].
During awakeFromNib one of these objects (an instance of MyModel) encounters a failure (due to name resolution).
An error message is displayed to the user, and the instance of MyWindowController, MyModel, and all other related instances are destroyed.
How would I accomplish step 4 in the most Cocoa-esque way?
Just to clarify: I know how to present an error to the user using NSError. I am trying to find out if the recommended/correct way to handle an error in awakeFromNib is to display the error and release everything from within awakeOnNib, or if there is a better way to do it (that may require restructuring my app).
The most brutally Cocoa manner in which to present an error is to use -[NSResponder presentError:].
If the object from which you issue this message inherits from NSResponder, you can use:
[self presentError:someError];
or if not, you could use this:
[[NSApplication sharedApplication] presentError:someError];
or alternatively:
[NSApp presentError:someError];
There are also variants of -presentError: that let you present your errors as window-modal sheets instead of application-modal dialogs.
All of this assumes that you've somehow got an instance of NSError to pass as someError. I'm not familiar with your model object. When you say it "encounters a failure," does that mean some method on your model class provides this error object? Or does a method on some other object that takes your model object as an argument provide the error? In either case, your method providing the error object should follow a form like this:
- (BOOL)myMethodReturningAnErrorByReference:(NSError **)error
or
- (id)myMethodReturningAnErrorByReference:(NSError **)error
In the former example, the method returns YES or NO, and in the case of NO, an instance of NSError should be returned by reference, which you can then present. In the latter example, your method returns either a valid reference to an object, or it returns nil, and in the case of nil, again, an instance of NSError should be returned by reference, which you can then present.
Furthermore, you can conditionally present the error by examining its code and domain properties. It's also possible to override -willPresentError: on your NSResponder inheriting class where you can customize the content of the presentation.
Finally, this page in Apple's online documentation provides a wealth of background information. I completely glossed over the error-responder chain used in presenting errors, but it's covered there.
Good luck to you in your endeavors.

Wiring NSToolBarItem with XIBs

For some reason I'm having a very difficult time wiring my NSToolbarItem to an IBAction.
I'm using an NSWindowController with its own XIB. The NSToolbar is dropped into the XIB, and I added the NSToolbarItem without issue. This whole NSWindowController is created by a master NSViewController when an image is clicked.
The problem lies with the new button not sending. I unchecked "Autovalidates" and checked "Selectable" so that I could actually click the button.
However when pressed, I receive "unrecognized selector sent to instance".
I've wired this several times over through the XIB interface to make sure I wasn't messing up.
What's going on? Thank you.
Full error:
-[__NSCFType buttonPressed:]: unrecognized selector sent to instance 0x101915010
The delegate class does not know the selector you've wired. Either your delegate is wrong or you've got a typing error in your method.
Check the signature of the Method you've declared in your headerfile vs. its implementation in the class file. Perhaps you forgot to declare a parameter.
edit:
the class type where the selector is called looked weird, so I googled __nscftype unrecognized selector. here are some suggestions, it seems like your delegate is already disposed :
http://imlocation.wordpress.com/2007/09/13/strange-objects-nscftype-indicate-memory-management-bugs/
[__NSCFType searchKeyword:]: unrecognized selector sent to instance 0x6d8eb80

Calling delegate method, unrecognized selector because sending to wrong object

In my app I do a lot of network loading. My data model consists of "Loader" objects that do this loading and call their delegate when finished/failed. The delegates all conform to a "LoaderDelegate" protocol.
The issue I'm having is that sometimes seemingly random objects, not the delegate, are getting the delegate messages. This of course causes a crash because of an unrecognized selector.
Only one set of crash logs tell me which one of my loaders is having the issue, the others don't have that information, just the random object that got the message.
I'm stuck at how to determine the real cause of this issue.
One set of crash logs has a loader trying to call it's delegate but reaching _UIImageViewExtendedStorage. Another has a loader is reaching __NSCFInputStream. Another __NSBlockVariable__. And yet another, CALayer.
And that's just in my latest beta from 3 days ago.
It would be one thing if it was the same object each time, but it seems almost random. Is it possible that memory is getting overritten with a new object somehow?
My delegate property for all of my loaders is an assign property, but the delegate is always alive when the loader finishes (delegates are my view controllers calling the loaders).
Please post some code, cause it is hard to troubleshoot. Remember to nil your delegate in the dealloc.
- (void) dealloc {
objectOfWhichIAmTheDelegate.delegate = nil;
}
What is more you the delegate should be an assign property not retain - but that's not a problem in your situation.
#property (assign) id<TheMightyDelegate> delegate;
Another thing you should do is to guarantee that the delegate responds to the selector you want to send to him before you fire the method.
if ([delegate respondsToSelector:#selector(yourMethod)]) {
[delegate performSelector:#selector(yourMethod)];
}
Hope this will put some light on your problem. If not please provide some code.
Turns out I was getting this error randomly all over the place, just not in this particular class and not just with delegate methods.
In my case, the problem turned out to be that I was accessing properties of various classes in multiple threads and those properties were nonatomic. Since I fixed that (removed nonatomic attribute of the properties), I haven't seen this happen anymore.

"unrecognized selector sent to instance" error in Objective-C

I created a button and added an action for it, but as soon as it invoked, I got this error:
-[NSCFDictionary numberButtonClick:]: unrecognized selector sent to instance
0x3d03ac0 2010-03-16 22:23:58.811
Money[8056:207] *** Terminating app
due to uncaught exception
'NSInvalidArgumentException', reason:'*** -[NSCFDictionary numberButtonClick:]: unrecognized selector sent to instance 0x3d03ac0'
This is my code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
UIButton *numberButton = [UIButton buttonWithType:UIButtonTypeCustom];
numberButton.frame = CGRectMake(10, 435, 46, 38);
[numberButton setImage:[UIImage imageNamed:#"one.png"] forState:UIControlStateNormal];
[numberButton addTarget:self action:#selector(numberButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview: numberButton];
}
return self;
}
-(IBAction)numberButtonClick:(id)sender{
NSLog(#"---");
}
It looks like you're not memory managing the view controller properly and it is being deallocated at some point - which causes the numberButtonClicked: method to be sent to another object that is now occupying the memory that the view controller was previously occupying...
Make sure you're properly retaining/releasing your view controller.
For those getting here via Google like I did, which probably pertains more to Xcode 4.2+/iOS 5+ more, what with ARC. I had the same error "unrecognized selector sent to instance". In my case I had a UIButton's target action set up to pass itself as the sender parameter, but later realised I didn't need it and removed that in code. So, something like:
- (IBAction)buttonPressed:(UIButton *)sender {
Was changed to:
- (IBAction)buttonPressed {
Right clicking the UIButton in question showed that the Touch Up Inside event was associated with the view controllers buttonPressed: method. Removing this and reassigning it to the modified method worked a treat.
This was the top Google answer for this issue, but I had a different cause/result - I thought I'd add in my two cents in case others stumble across this problem.
I had a similar issue just this morning. I found that if you right click the UI item giving you the issue, you can see what connections have been created. In my case I had a button wired up to two actions. I deleted the actions from the right-click menu and rewired them up and my problem was fixed.
So make sure you actions are wired up right.
OK, I have to chip in here. The OP dynamically created the button. I had a similar issue and the answer (after hours of hunting) is so simple it made me sick.
When using:
action:#selector(xxxButtonClick:)
or (as in my case)
action:NSSelectorFromString([[NSString alloc] initWithFormat:#"%#BtnTui:", name.lowercaseString])
If you place a colon at the end of the string - it will pass the sender. If you do not place the colon at the end of the string it will not, and the receiver will get an error if it expects one. It is easy to miss the colon if you are dynamically creating the event name.
The receiver code options look like this:
- (void)doneBtnTui:(id)sender {
NSLog(#"Done Button - with sender");
}
or
- (void)doneBtnTui {
NSLog(#"Done Button - no sender");
}
As usual, it is always the obvious answer that gets missed.
In my case the function was not expecting an argument but the button was configured to send one causing the error. To fix this I had to rewire the event handler.
Here is my function:
Notice it contains no arguments.
Here is an image of my button configuration (right click on the button to view it):
Notice there are 3 event handlers.
To fix this I had to remove each of the event items since one of them was sending a reference to itself to the enterPressed function. To remove these items I clicked on the little x icon next to the name of each item until there were no items shown.
Next I had to reconnect the button to the event. To do this hold down the Control key and then drag a line from the button to the action. It should say "Connect Action". Note: I had to restart XCode for this to work for some reason; otherwise it only let me insert actions (aka create a new action) above or below the function.
You should now have a single event handler wired to the button event that passes no arguments:
This answer compliments the answer by #Leonard Challis which you should read as well.
This can also happen if you don't set the "Class" of the view in interface builder.
In my case, I was using NSNotificationCenter and was attempting to use a selector that took no arguments, but was adding a colon. Removing the colon fixed the problem.
When using a selector name, don't use a trailing colon if there are no arguments. If there's one argument, use one trailing colon. If there are more than one argument, you must name them along with a trailing colon for each argument.
See Adam Rosenfield's answer here: Selectors in Objective-C?
I had this problem with a Swift project where I'm creating the buttons dynamically. Problem code:
var trashBarButtonItem: UIBarButtonItem {
return UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "newButtonClicked")
}
func newButtonClicked(barButtonItem: UIBarButtonItem) {
NSLog("A bar button item on the default toolbar was clicked: \(barButtonItem).")
}
The solution was to add a full colon ':' after the action: e.g.
var trashBarButtonItem: UIBarButtonItem {
return UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "newButtonClicked:")
}
func newButtonClicked(barButtonItem: UIBarButtonItem) {
NSLog("A bar button item on the default toolbar was clicked: \(barButtonItem).")
}
Full example here: https://developer.apple.com/library/content/samplecode/UICatalog/Listings/Swift_UIKitCatalog_DefaultToolbarViewController_swift.html
The most obvious cause of this (included for completeness) is improperly casting a pointer and calling a method of the wrong class.
NSArray* array = [[NSArray alloc] init];
[(NSDictionary*)array objectForKey: key]; // array is not a dictionary, hence exception
I also had the same issue.
I deleted my uibutton in my storyboard and recreated it .. now everything works fine.
How to debug ‘unrecognized selector send to instance’
In most of the cases Xcode do not take us to the exact line where this issue happen. When app crash you won’t see the line of code that caused this, rather you will be taken to App delegate class, in which the error output may look like:
[UITableViewCellContentView image]: unrecognized selector sent to instance
or
[__NSDictionaryI objectAtIndex:] unrecognized selector sent to instance
or
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TestApp.MyViewController viewDidLoad:]: unrecognized selector sent to instance 0xDABCDD'
How to find line of code causing this:
Go to breakpoint navigator. Click ‘+’ option. click ‘Exception Breakpoint’. An new widget like following will apear.
Add following condition block:
-[NSObject(NSObject) doesNotRecognizeSelector:]
You can also put breakpoint for all exception.
Now run your code again. this time, breakpoint will trigger when this exception occurs.
WRITTEN BY: Prafulla Singh
Full explanition: https://prafullkumar77.medium.com/how-to-debug-unrecognized-selector-send-to-instance-402473bc23d
I had a similar problem, but for me the solution was slightly different. In my case, I used a Category to extend an existing class (UIImage for some resizing capabilities - see this howto in case you're interested) and forgot to add the *.m file to the build target. Stupid error, but not always obvious when it happens where to look. I thought it's worth sharing...
Another possible solution: Add '-ObjC' to your linker arguments.
Full explanation is here: Objective-C categories in static library
I think the gist is: if the category is defined in a library you are statically linking with, the linker isn't smart enough to link in category methods. The flag above makes the linker link in all objective C classes and categories, not just ones it thinks it needs to based on analyzing your source. (Please feel free to tune or correct that answer. I'm knew to linked languages, so I'm just parroting here).
This happened to my because accidentally erase the " #IBAction func... " inside my UIViewcontroller class code, so in the Storyboard was created the Reference Outlet, but at runtime there was any function to process it.
The solution was to delete the Outlet reference inside the property inspector and then recreate it dragging with command key to the class code.
Hope it helps!
I think you should use the void, instead of the IBAction in return type. because you defined a button programmatically.
I had the same error and I discovered the following:
When you use the code
[self.refreshControl addTarget:self action:#selector(yourRefreshMethod:) forControlEvents:UIControlEventValueChanged];
You may think it's looking for the selector:
- (void)yourRefreshMethod{
(your code here)
}
But it's actually looking for the selector:
- (void)yourRefreshMethod:(id)sender{
(your code here)
}
That selector doesn't exist, so you get the crash.
You can change the selector to receive (id)sender in order to solve the error.
But what if you have other functions that call the refresh function without providing a sender? You need one function that works for both. Easy solution is to add another function:
- (void)yourRefreshMethodWithSender:(id)sender{
[self yourRefreshMethod];
}
And then modify the refresh pulldown code to call that selector instead:
[self.refreshControl addTarget:self action:#selector(yourRefreshMethodWithSender:) forControlEvents:UIControlEventValueChanged];
I'm also doing the Stanford iOS course on an older Mac that can't be upgraded to the newest version of Mac OSX. So I'm still building for iOS 6.1, and this solved the problem for me.
On my case I solved the problem after 2 hours :
The sender (a tabBar item) wasn't having any Referencing Outlet. So it was pointing nowhere.
Juste create a referencing outlet corresponding to your function.
Hope this could help you guys.
I'm currently learning iOS development and going through the "Beginning iOS6 Development" book by aPress. I was getting the same error in Chapter 10:Storyboards.
It took me two days to figure it out but found out I accidentally set the TableView cell's tag to 1 when I shouldn't have. For anyone else doing this book and receive a similar error I hope this helps.
I really hope future errors in my code are easier to find! hahaha. The debug error did nothing to push me in the right direction to figuring it out (or at least I'm too new to understand the debugger, lol).
In my case I was using a UIWebView and I passed a NSString in the second parameter instead of a NSURL. So I suspect that wrong class types passed to a functions can cause this error.
..And now mine
I had the button linked to a method which accessed another button's parameter and that worked great BUT as soon I tried to do something with the button itself, I got a crash. While compiling, no error has been displayed.. Solution?
I failed to link the button to the file's owner. So if anyone here is as stupid as me, try this :)
Yet another slightly different solution/case.
I am using Xamarin and MvvmCross and I was trying to bind the UIButton to a ViewModel. I had the UIButton wired up to an Outlet and a TouchUpInside.
When Binding I only use the Outlet:
set.Bind (somethingOutlet).For ("TouchUpInside").To(vm => vm.Something);
All I had to do was remove the action (TouchUpInside) connection in XCode and that solved it.
P.S.
I guess this is in its base all related to the previous answers and to #Chris Kaminski in particular, but I hope this helps someone...
Cheers.
I had the same issue. The problem for me was that one button had two Action methods. What I did was create a first action method for my button and then deleted it in the view controller, but forgot to disconnect the connection in the main storyboard in the connection inspector. So when I added a second action method, there were now two action methods for one button, which caused the error.
For me, it was a leftover connection created in interfacebuilder bij ctrl-dragging. The name of the broken connection was in the error-log
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[NameOfYourApp.NameOfYourClass nameOfCorruptConnection:]:
unrecognized selector sent to instance 0x7f97a48bb000'
I had an action linked to a button. Pressing the button crashed the app because the Outlet no longer existed in my code.
Searching for the name in the log led me to it in the storyboard. Deleted it, and the crash was gone!
I'm replying to Leonard Challis, since I was also taking the Stanford iOS class C193P, as was user "oli206"
"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:"
The problem was that I had the "Enter" button on the calculator connected twice,and a friend pointed out that doing an inspection of the button in the Storyboard showed that 2 entries were on the "Touch Up Inside" attributes when I right clicked on the "Enter" button. Erasing one of the two "Touch Up Inside" "Sent Events" solved the problem.
This showed that the problem is triggered (for the C193P video class on the Calculator Walkthrough on Assignment 1) as 2 sent events, one of which was causing the exception.
It can happen when you do not assign the ViewController to the ViewControllerScene in
the InterfaceBuilder. So the ViewController.m is not connected to any scene.
Including my share. I got stuck on this for a while, until I realized I've created a project with ARC(Automatic counting reference) disabled. A quick set to YES on that option solved my issue.
Another really silly cause of this is having the selector defined in the interface(.h) but not in the implementation(.m) (p.e. typo)
Another reason/solution to add to the list. This one is caused by iOS6.0 (and/or bad programming). In older versions the selector would match if the parameter types matched, but in iOS 6.0 I got crashes in previously working code where the name of the parameter wasn't correct.
I was doing something like
[objectName methodName:#"somestring" lat:latValue lng:lngValue];
but in the definition (both .h and .m) I had
(viod) methodName:(NSString *) latitude:(double)latitude longitude:(double)longitude;
This worked fine on iOS5 but not on 6, even the exact same build deployed to different devices.
I don't get why the compiler coudn't tell me this, anyway - problem soled.
This also might happen when you want to set a property from a ControllerA to a public property inside a custom ControllerB class and you haven't set the "Custom Class" inside the identity inspector in storyboards yet.
My problem and solution was different and I thought I should post it here so that future readers can save their head from banging to the wall.
I was allocating different xib to same UIVIewController and even after searching everywhere I couldn't find how to correct it. Then I checked my AppDelegate where I was calling initWithNibName and can see that while copying the code, I changed the xib name, but forgot to change UIViewController class. So if none of the solution works for you, check your initWithNibName method.