Unrecognized selector sent to instance" problem - iphone

my code broke somewhere along the way, and crashes when using the navigation bar buttons.
Error message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView newMemoViewController:didAddMemo:]: unrecognized selector sent to instance 0x5b55a60'
When debugging, the program does run the cancel method, and throws an exception at the #synthesize line. However, I cannot see anything wrong with it.
The symptoms are identical, so I am including the relevant code only for the Cancel button:
NewMemoViewController.h
#import <UIKit/UIKit.h>
#protocol NewMemoDelegate;
#class AKVoiceMemo;
#interface NewMemoViewController : UIViewController {
#private
AKVoiceMemo *voiceMemo;
id <NewMemoDelegate> delegate;
}
#property (nonatomic, retain) AKVoiceMemo *voiceMemo;
#property (nonatomic, assign) id <NewMemoDelegate> delegate;
#end
#protocol NewMemoDelegate <NSObject>
- (void)newMemoViewController:(NewMemoViewController *)newMemoViewController didAddMemo:(AKVoiceMemo *)voiceMemo;
#end
NewMemoViewController.m
#import "NewMemoViewController.h"
#synthesize delegate;
- (void)viewDidLoad {
UIBarButtonItem *cancelButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(cancel)];
self.navigationItem.leftBarButtonItem = cancelButtonItem;
[cancelButtonItem release];
}
- (void)cancel {
[self.delegate newMemoViewController:self didAddMemo:nil];
}
Your help would be appreciated.
Edit: the delegate is the RootViewController:
- (void)newMemoViewController:(NewMemoViewController *)newMemoViewController didAddMemo:(AKVoiceMemo *)voiceMemo {
if (voiceMemo){
// Show the note in a new view controller
// TODO: Implement this
}
[self dismissModalViewControllerAnimated:YES];
}

You're probably setting the delegate of NewMemoViewController to a UIView object instead of an object that implements the NewMemoDelegate protocol.
The error message is telling you that a newMemoViewController:didAddMemo: message was sent to a UIView object and the UIView object didn't know what to do with it. Since your cancel method calls newMemoViewController:didAddMemo: on the delegate, it is the delegate which is the UIView object that doesn't recognize the newMemoViewController:didAddMemo: message. In other words, your delegate is a UIView and it doesn't implement the NewMemoDelegate protocol.
If you are correctly setting the delegate, then #jtbandes makes a great point: The delegate is probably being released and a UIView object is taking over the same memory location, thus "becoming" the delegate by accident. You're doing the right thing by using the assign attribute for your delegate; that's fairly standard Cocoa practice. However, you do need to make sure that the delegate is retained by another object, and that object needs to make sure that the delegate sticks around as long as NewMemoViewController needs it to.

I'm guessing you've over-released the delegate. I notice you have #property (assign) ... delegate;. This means that whenever you set the delegate, that object must be retained by something else as well.
The other possibility is the delegate is actually a UIView, but I'm guessing it's the other case.

Related

One delegate class for multiple NSFetchedResultsController?

I have several NSFetchedResultsControllers throughout my app, and in every view controller, I implement the respective delegate methods. However, instead of copying these delegate methods into every class that implements an NSFetchedResultsController, I thought I would just create a class that implements these delegate methods, and set all fetched results controller's delegate to point to that one class. Here's what I've tried, which doesn't work:
Since the delegate methods need to know which table view they are making changes to, I thought I would just create a separate delegate class for each fetched results controller, and send a pointer to the tableview for that class:
FetchedResultsDelegate *delegate = [[FetchedResultsDelegate alloc] initWithTableView:parentTableView];
self.fetchedResultsController.delegate=delegate;
[delegate release];
However, this causes a BAD_ACCESS crash, so this means that I probably shouldn't be doing what I'm doing above.
How can I create a single delegate class that handles all delegate requests for all my NSFetchedResultsControllers?
Edit: I was able to fix the problem by doing #property (nonatomic, retain) FetchedResultsDelegate *delegate; Is this ok? Some people are saying something about assign rather than retain?
Nothing is retaining your FetchedResultsDelegate as delegate properties are normally declared as assign. e.g. NSFetchedResultsController declares the delegate as
#property(nonatomic, assign) id <NSFetchedResultsControllerDelegate> delegate
Therefore you created the object and destroyed it straight away, but gave the fetchedResultsController a nasty dangling pointer.
To fix this you need a retain on the delegate. So in your UITableViewController class add a new property
// .h
#property (nonatomic, strong) id<NSFetchedResultsControllerDelegate> tableViewDelegate;
// .m
#synthesize tableViewDelegate = _tableViewDelegate;
then when you hook up you delegate just change your code to this
FetchedResultsDelegate *delegate = [[FetchedResultsDelegate alloc] initWithTableView:parentTableView];
self.fetchedResultsController.delegate = delegate;
self.tableViewDelegate = delegate;
[delegate release]; delegate = nil;
Don't forget
Release this new ivar in the dealloc
- (void)dealloc;
{
// ... other releases
[_tableViewDelegate release];
[super dealloc];
}
The use of assign is all about ownership semantics.
In this case your UITableViewController should own the tableView's delegate (e.g. strong/retain) as nothing else is.
The reason that the NSFetchedResultsController uses assign and not retain/strong is because there is a good chance that the object that created it would act as the delegate, which would result in both objects owning each other (both having a retain held on each other), which causes a retain cycle

singleton, public, or global variable use

I have searched and tried every example regarding singleton, public, and global variables in stack overflow on this subject. I'm making a mistake some where. I have a settings variable called strIP that is part of a textField and is declared in my secondViewController.h. I want this variable to used in a class called myWSupdate.m. It's just one variable I wanna pass it to a connection string. this compiles correctly but the app crashes on run. What am I doing incorrectly?
error from complier:Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[SecondViewController sharedIP]: unrecognized selector sent to class 0x6403c'
secondViewController.h
#interface SecondViewController : UIViewController
{
UITextField *ipAdd;
NSString *strIP;
}
#property (nonatomic, retain) IBOutlet UITextField *ipAdd;
#property (retain) NSString *strIP;
+(SecondViewController*)sharedIP;
then I call it in myWSupdate.m:
#import "SecondViewController.h"
/* Implementation of the service */
#implementation myWSupdate
- (id) init
{
if(self = [super init])
{
SecondViewController* IP = [[SecondViewController sharedIP]init];
NSLog(#"the test has %#", IP.strIP);
}
}
#end
Since strIP belongs to a SecondViewController, you need to reference it as part of that object.
How to do that depends on the relationship between SecondViewController and myWSupdate. (For example, if the controller creates a myWSupdate object, you could pass the variable as part of the init.)
The fact that it's marked public doesn't change the fact that it's an instance variable and therefore needs to be used in connection with an instance of its class.

message sent to deallocated instance 0x141dafb0 iPhone SDK

i am getting this error "message sent to deallocated instance 0x141dafb0" its comming from a UIBarButtonItem when its beeing pressed on the application. any help would be greatly appreciated
Error:
*** -[PeerConnection performSelector:withObject:withObject:]: message sent to deallocated instance 0x14143ff0
PeerConnection.h
#import <UIKit/UIKit.h>
#import <GameKit/GameKit.h>
#interface PeerConnection : NSObject <GKPeerPickerControllerDelegate, GKSessionDelegate> {
UIBarButtonItem *StartConnection;
}
- (IBAction) StartConnectionAction;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *StartConnection;
#end
PeerConnection.m
#import "PeerConnection.h"
#implementation PeerConnection
#synthesize StartConnection;
- (IBAction) StartConnectionAction {
NSLog(#"Start Connection to the other IPhones");
[StartConnection release];
}
- (void)dealloc {
[super dealloc];
}
#end
i have enabled Zombie and that is all its giving to me
Don't release your StartConnection button until -dealloc. Releasing that bar button item in -StartConnectionAction is your problem--anything the UI tries to do with it after that will call a zombie.
In your case, you have released the StartConnection object. Now, when the automatic dealloc is called, the reference was not found (as already removed) and hence you got the error.
I had the same error, but was using a singleton with autorelease on shared method, took off autorelease from there and added on it's dealloc , and all works fine now.
Old Thread; But thought I might add.
If your app isn't using ARC; Use The Analyse Feature to find all the problems that may arise due to releasing/retaining objects.
Shortcut is command + shift + B
Totally useful !
This may be due to access of the instance that is already removed during GC. The error occurs in a case when you use autorelease.
ThePlannerAppDelegate *delg = [(ThePlannerAppDelegate *)[[UIApplication sharedApplication] delegate] autorelease];
Now this is most likely the GC will destroy the reference although delg points to the main window delegate.
My point is use autorelease safely.
Important: The error will occur when a message will be sent to an dead reference.

Pushing a UIViewController doesn't work with connections

Alright, in my rootViewController, I am able to push another viewController that I defined myself onto the screen. However, when I make any connections between that viewController and its own .h file, the program just hangs and crashes, giving me this error:
2010-06-04 15:36:13.944 pooldocfinal[11971:20b] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key label1.'
That happens when i don't connect anything besides that one UILabel. Here is the code I use to declare/push the view (named balanceViewController):
- (IBAction) pushedBalanceButton
{
balanceViewController *controller = [[balanceViewController alloc] initWithNibName:#"balanceViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
And here is the .h file of the view that I am pushing, it has only one thing in it:
#import <UIKit/UIKit.h>
#interface balanceViewController : UIViewController {
IBOutlet UILabel *label1;
}
#end
And like I said, everything works unless I actually make a connection in Interface Builder between anything in balanceViewController.xib and balanceViewController.h (in this case, it is the one UILabel object).
You should alloc a balanceViewController, not a UIViewController.
I believe if you have an IBOutlet, you need to define getters/setters. That's what Key Value coding compliant means. You can do this via #property statements and #synthesize statements, or manually if you so choose.
#interface balanceViewController : UIViewController {
IBOutlet UILabel *label1;
}
#property (nonatomic, retain) IBOutlet UILabel *label1;
#end
Then add
#synthesize label1;
to your implementation
EDIT - PS, don't forget to [label1 release] in your dealloc method

iphone: Implement delegate in class

I am trying to call up a modal table view controller using presentModalViewController but I am not sure what to do about the delegate. The following code gives me an error:
MyRidesListView *controller = [[MyRidesListView alloc] init];
controller.delegate = self;
[self presentModalViewController:controller animated:YES];
[controller release];
Error:
Request for member 'delegate' is something not a structure or union
Now, I realized there is no delegate property in my MyRidesListView class. So, how would I add a reference to my delegate there? What am I missing here?
Generally delegates are properties defined as such:
id<NameOfDelegateProtocol> delegate;
And:
#property (nonatomic, assign) id<NameOfDelegateProtocol> delegate;
EDIT: You said your parent class is UITableViewController. You may have wanted to do this:
controller.tableView.delegate = self;
Why do you think you need a delegate? Why not just remove the "controller.delegate = self" line. Otherwise you need to implement a delegate system the way I outline below or else make MyRidesListView a subclass of a viewcontroller that implements delegates.
It looks like you cut and pasted some sample code that uses a delegate, then substituted your own viewcontroller that doesn't provide a delegate. If you don't know what the delegate is for, then just delete that line.
I'll cut and paste some actual code from one of my test programs to show you how it's done:
from the Interface file:
Add a delegate instance variable to your class and make it a property so you can use the "blah.delegate = foo" syntax to set it.
#interface BAPClient : NSObject {
CGSize imageSize;
id <BAPClientDelegate> delegate;
}
#property (nonatomic, readonly) CGSize imageSize;
#property (nonatomic, assign) id <BAPClientDelegate> delegate;
#end
// define the protocol spoken. (what the delegate must implement)
#protocol BAPClientDelegate
- (void)addTile:(BAPTile *)tile;
#end
in the implementation, you must call the delegate at the appropriate time:
- (void)deliverTile:(BAPTile *) tile {
NSLog(#"%s tile=%p",__FUNCTION__,tile);
if ([self delegate])
[[self delegate] addTile:tile];
[tile release];
}
Try to set the delegate object by the setter
[controller setDelegate:self];
This often works wonders.