I have created a simple app using the AsynUDPSocket class. It listens to simple text messages from a UDP client.
When I put the relevant code into a view controller, everything works fine. But when I try the same in the app delegate my app crashes. This thing worked fine in the app delegate a few days back. Now I dont know what's wrong.
I used the code from this post
.Can someone please elaborate?
EDIT: Code
My App Delegate's .h file contents
//
// MacSocketTestAppDelegate.h
// MacSocketTest
//
// Created by core on 04/05/11.
// Copyright __MyCompanyName__ 2011. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AsyncUdpSocket.h"
#import "SocketController.h"
#import "NextController.h"
#class SocketController;
#class SocketTest;
#interface MacSocketTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
SocketTest *connection;
AsyncUdpSocket *aSyncSocket;
UIViewController *currentViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet SocketController *mySC;
#property (nonatomic, retain) SocketTest *connection;
#property (nonatomic, retain) AsyncUdpSocket *aSyncSocket;
#property (nonatomic, retain) UIViewController *currentViewController;
#end
My App Delegate's .m file contents
//
// MacSocketTestAppDelegate.m
// MacSocketTest
//
// Created by core on 04/05/11.
// Copyright __MyCompanyName__ 2011. All rights reserved.
//
#import "MacSocketTestAppDelegate.h"
#import "SocketController.h"
#import "SocketTest.h"
#import "NextController.h"
#implementation MacSocketTestAppDelegate
#synthesize window;
#synthesize mySC;
#synthesize connection;
#synthesize aSyncSocket;
#synthesize currentViewController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
aSyncSocket=[[AsyncUdpSocket alloc] initWithDelegate:self]; //We are the delegate for the asynchronous socket object.
[aSyncSocket bindToPort:30000 error:nil]; //We want to listen on port 30000. Don't care about errors for now.
[aSyncSocket receiveWithTimeout:-1 tag:1]; //Start listening for a UDP packet.
SocketTest *instanceST = [SocketTest alloc];
[self setConnection:instanceST];
SocketController *instanceSocketController = [[SocketController alloc] initWithNibName: #"SocketController" bundle: nil];
[self setMySC:instanceSocketController];
[instanceSocketController release];
[[self window] setRootViewController:[self mySC]];
[window makeKeyAndVisible];
return YES;
}
//Other methods hidden
#pragma mark AsyncUdpSocket Delegate Method
//This method is called by the AsyncUdpSocket object when a packet is received:
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
{
NSString *theLine=[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; //Convert the UDP data to an NSString
NSLog(#"%#", theLine);
[theLine release];
[aSyncSocket receiveWithTimeout:-1 tag:1]; //Listen for the next UDP packet to arrive...which will call this method again in turn.
return YES; //Signal that we didn't ignore the packet.
}
- (void)dealloc {
[window release];
[super dealloc];
}
#end
EDIT: Crash log
The Debugger has exited with status 0.
[Session started at 2011-05-05 15:29:18 +0530.]
GNU gdb 6.3.50-20050815 (Apple version gdb-1469) (Wed May 5 04:36:56 UTC 2010)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".sharedlibrary apply-load-rules all
Attaching to process 1706.
Pending breakpoint 1 - ""MacSocketTestAppDelegate.m":41" resolved
MacSocketTest(1706) malloc: recording malloc stacks to disk using standard recorder
MacSocketTest(1706) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly
MacSocketTest(1706) malloc: process 1547 no longer exists, stack logs deleted from /tmp/stack-logs.1547.MacSocketTest.bEuUBJ.index
MacSocketTest(1706) malloc: stack logs being written into /tmp/stack-logs.1706.MacSocketTest.SJLaue.index
(gdb) continue
Current language: auto; currently objective-c
2011-05-05 15:29:46.698 MacSocketTest[1706:207] *** -[MacSocketTestAppDelegate respondsToSelector:]: message sent to deallocated instance 0x5954e00
(gdb)
Thanks,
Angelo.
Well, with the information you're giving us I would guess you probably messed up the memory management. I guess so because that's the most common cause for crashes.
I used the code from this post.
What post? There's no code in this post.
In order to get a decent answer that's not just based on statistical reasons for crashes you should provide code, crash log and stack trace.
EDIT: So you edited in the link. So now we have some code. However that code is out of context and you've already told us that it works, so we're not going to find the answer there.
EDIT 2:
2011-05-05 15:29:46.698 MacSocketTest[1706:207] *** -[MacSocketTestAppDelegate respondsToSelector:]: message sent to deallocated instance 0x5954e00
So I was right. It was a memory issue. You're sending a message to a deallocated object. What's weird is that it seems to be your app delegate that has been deallocated.
Erik, your comments were spot on. I have figured out my problem's location.
Let me explain:
Like I commmented, I'm moving from the app delegate to one screen, and from that screen to another one.
In essence, in the last screen's (view's) view controller, I was creating an instance of my app delegate to set the last screen's view controller as my currentViewController property of my app delegate. I'm maintaining it for different reasons.
I was, also, DEALLOCATING, the instance of the app delegate right after I was done setting my currentViewController property. Once I removed that line, I was good and my app was up and running.
I think I should deallocate it in the dealloc method. Please correct my understanding, if I'm wrong.
Thanks a million to you, Erik, for pointing me in the right direction.
EDIT: Erik, please tell me how you knew from the crash logs, that it was my app delegate that was being deallocated it.
Angelo.
Related
First off, the disclaimer is I'm targeting iOS 5, so that very well may be the source of my issues, but if not...
I'm trying to write a simple class that manages location updates through CoreLocation. However, I see some pretty strange behavior. I have a custom class which basically wraps CLLocationManager and the delegate methods. This is the interface:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#protocol CLZipCodeFetcherDelegate
#optional - (void)didReceiveZipCode:(NSString *)zipCode;
#end
#interface CLZipCodeFetcher : NSObject <CLLocationManagerDelegate> {
id <CLZipCodeFetcherDelegate> delegate;
CLLocationManager *locationManager;
}
#property (strong, readwrite) id <CLZipCodeFetcherDelegate> delegate;
#property (strong, read write) CLLocationManager *locationManager;
- (void)getZipCode;
#end
and the implementation (ignore the zip code related stuff- that's what the class is eventually meant to do, but right now I'm just trying to get some coordinates back from CoreLocation):
#import "CLZipCodeFetcher.h"
#implementation CLZipCodeFetcher
#synthesize delegate, locationManager;
- (id) init {
self = [super init];
if (self != nil) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = 10.0f; // we don't need to be any more accurate than 10m
self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
self.locationManager.purpose = #"Retrieve zip code";
}
return self;
}
- (void)getZipCode {
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(#"Received location");
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"Location failed");
}
#end
And then I initialize an instance of the class in my view controller and call the method:
CLZipCodeFetcher *zipCodeFetcher = [[CLZipCodeFetcher alloc] init];
[zipCodeFetcher getZipCode];
Now, when I run this, the app takes a moment to load, and then pops up the alert dialog asking for permission to let the app use location services. However, as soon as it appears, it immediately disappears (too fast to let me hit the allow or deny button), and nothing happens (no delegate methods are called). If I then go into the Location Settings of the device, it indeed shows 'Off' for my app. When I turn it on manually from that screen and then go to try the app again, no alert dialog appears, but still nothing happens. Neither of my debug messages are logged. The behavior is the same on both the simulator and my iPhone 4.
So basically, anyone have any idea why? I've looked through all the similar threads, and many issues were related to memory management, but I don't think that'd be a problem here since ARC should be managing my CLLocationManager object, right?
P.S. Also, I did add the CoreLocation framework to my project, and I get no code errors or warnings, but is there anything else I need to do before using CoreLocation in my app?
ARC is deallocating your newly created object after the getZipCode method call.
I have not used ARC yet so I'm not sure of your syntax in the header (readwrite vs. read write).
But I would put an NSLog(#" my loc manager is %#", self.locationManager); inside of getZipCode just to make sure you've got one and it's not being released before it has a chance to do anything.
At present I'm building a basic application to learn Objective-C and the iPhone SDK.
I'm creating NSObject with getters and setters to get to grips with how these works. I've successfully added a property and getters and setters to my main controller, currently I'm trying to create a separate class which I can create a new instance of within my controller but it crashes when I try and use the setter.
Thank you in advance for your time, sorry if this question is as stupid as I'm sure it is.
Here's the header for my class
QuizQuestion.h
#import <Foundation/Foundation.h>
#interface QuizQuestion : NSObject {
NSString *question;
}
#property (retain) NSString* question;
#end
QuizQuestion.m
#import "QuizQuestion.h"
#implementation QuizQuestion
#synthesize question;
- (void) dealloc
{
[question release];
[super dealloc];
}
#end
And here is my controller code (i've cut some out)
#implementation Quiz2ViewController
#class QuizQuestion; // Is this correct?
- (void)viewDidLoad {
QuizQuestion *aQuestion;
//gets here fine, but crashes (the app closes) when I set question.
[aQuestion setQuestion:#"hello world"];
[super viewDidLoad];
}
#end
As well as #class I tried import "QuizQuestion.h" and I get the same issue.
You're not actually allocating an instance of the QuizQuestion class—your aQuestion variable isn’t pointing to anything in particular, so trying to send it a message, like -setQuestion:, is sending that message to... well, there’s no telling where, and sending things messages that aren’t meant for them is a surefire way to crash your app. What you need to do is this:
QuizQuestion *aQuestion = [[QuizQuestion alloc] init];
[aQuestion setQuestion:#"hello world"];
You also need to call [aQuestion release] at some point, or you’ll leak the memory associated with it.
You need to allocate space and initialize the QuizQuestion.
QuizQuestion *aQuestion = [[QuizQuestion alloc] init];
before setting the question.
I think you need to read up on some documentation before you try any more coding. Apple has several intro programming guides that are very good. The problem you are having is addressed in this section:
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocAllocInit.html
QuizQuestion *aQuestion = [[QuizQuestion alloc] init];
[aQuestion setQuestion:#"hello world"];
[aQuestion release];
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.
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.
I'd like to display the contents of the property myarray, from the following singleton:
[Session sharedManager].myarray
I've tried these:
po [Session sharedManager]. myarray
po [[Session sharedManager] myarray]
but always get this error:
A syntax error near end of expression.
Any suggestions?
--- EDIT ---
I'm working with SDK 3.0.
I've discovered the problem, which is I had three open brackets rather than two. You can't see that here because I mistyped the number of brackets. It is working now. Thanks.
If you use XCode Debugger and you set a breakpoint in the some place that the variable is already initialized and can be seen, you can click to the variable and choosing Print Description.
You can do it in simple way like NSLog(). What is the problem with this approach? Usually, I see that it will print out all the description() method of all objects in the array?
And I am not sure, but you lack a semicolon at the end of the statement. ";", can you recheck for that one?
What you are describing is very strange. I set up a test application and was able to print the object from the singleton just fine.
#import "testAppDelegate.h"
//A Session Singleton
#interface Session : NSObject {
NSArray *myArray;
}
#property (nonatomic, retain) NSArray *myArray;
#end
#implementation Session
#synthesize myArray;
static Session *sharedSession;
+(Session *)sharedSession {
if (!sharedSession) {
sharedSession = [[Session alloc] init];
sharedSession.myArray = [NSArray arrayWithObjects:#"A",#"B",#"C",nil];
}
return sharedSession;
}
#end
//App Delegate
#implementation testAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"%#",#"Breakpoint Here"); //Here is where I set My breakpoint
return YES;
}
- (void)dealloc {
[super dealloc];
}
#end
In GDB:
(gdb) po [[Session sharedSession] myArray]
<NSCFArray 0x4710630>(
A,
B,
C
)
I did this using the 3.2 iPhone SDK, using a default project template, in the debug mode without changing any build settings. I suspect you may have issues in your build settings. I have noticed that debugging is wonky on the 4.0 beta sdks. If you are using 4.0, remember that it is still beta, and your problems may really be someone else's problems.