well coded exception handling - #try #catch or without it - iphone

I want to know the global mechanism for exception handling.
Like I do have 20 different classes and I want to put try catch in all , then It may be some what time consuming as well as may can create issues.
I found some code like
-(void)ExceptionOccure:(NSException *)exception
{
NSArray *stack = [exception callStackReturnAddresses];
NSLog(#"%#", stack);
}
But I am not able to call this method , using
-(void) applicationDidFinishLaunching: (UIApplication *) application
{
NSSetUncaughtExceptionHandler (&ExceptionOccure);
}
I came to know this way but not able to call any exception.
I want to create global mechanism for this exception handling. so that in any class if any exception occurs it will call the above written function and handle the exception as well as can store the stack in the database as I needed.
Can any one suggest me or provide me sample code for handling exception globally..
thanks in advance

your handler function is a C function so you have to implement it like this :
static void uncaughtExceptionHandler(NSException *exception)
{
NSArray *stack = [exception callStackReturnAddresses];
NSLog(#"%#", stack);
}
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
}

Related

Block inside block = EXC_BAD_ACCESS

I have a singleton class the handle all the Game Center logic:
typedef void (^GameCenterCallbackFinishUpdating)();
- (void)getAllMatches:(GameCenterCallbackFinishUpdating)onComplete
{
[GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error)
{
//Do stuff here...
onComplete();
}];
}
From another viewController I use:
[[GameCenterHelper sharedHelper] getAllMatches:^{
[self.myTableView reloadData];
}];
It works great when I'm in the app, but once I close the app (background) and then start it up again, I get:
onComplete(); ---- Thread 1: EXC_BAD_ACCESS (code=2, address=0xc)
What am I doing wrong here?
some background info: the blocks are objects and if any block is nil and you try to call them, it crashes the application.
somewhere and somehow the block onComplete becomes nil before you call it. the following if (...) statement helps you to prevent to call a nil pointer, so the application won't crash.
if (onComplete) onComplete();
Thanks to #holex and #Paul.s for explaining it well.
I had the similar situation where I was sending block as method parameter(completionHandler).
- (void)callX:(NSString *)xyz withCompletionHandler:(void (^)(NSString *response))completion
{
completion(something);
}
And there are two situations either I am using this block like:
[MyClass sharedInstance] callX:#"abc" withCompletionHandler:^(NSString *response) {
if (response) {
//do something
}
}];
or this block could be nil as method parameter:
[MyClass sharedInstance] callX:#"abc" withCompletionHandler:nil];
In second case when block was being passed nil as method parameter this caused EXC_BAD_ACCESS on completion(). So as #holex states that the blocks are objects and if any block is nil and you try to call them, it crashes the application.
A single if saves lot of my time
- (void)callX:(NSString *)xyz withCompletionHandler:(void (^)(NSString *response))completion
{
if (completion)
completion(something);
}
P.S: this explanation only for NERDS like me. | ' L ' |

Determine if an object is being accessed by more than one thread?

I'm getting sporadic EXC_BAD_ACCESS crashes which I'm thinking has to do with multi-threading issues. (I tried profiling with Zombies, but the app doesn't crash when profiling). So I'm wondering if there is any sort of mechanism, for debugging purposes, to determine if an object is being simultaneously accessed by more than one thread? Maybe somehow print a log statement if that is the case?
A simple and dirty method of telling if you are the only one executing on a thread would rely on unguarded static variables:
-(void)concurrentMethod {
static NSThread *runningThread = nil;
NSThread *myThread = [NSThread currentThread];
if (runningThread != nil) {
NSLog(#"Thread %#: running concurrently with %#", runningThread, myThread);
}
runningThread = myThread;
... // Do the useful stuff here
if (runningThread != myThread) {
NSLog(#"Thread %#: pre-empted by %#", myThread, runningThread);
}
runningThread = nil;
}

Why aren't library (delegate) methods getting invoked? CocoaAsyncSocket

I have been stuck on this issue for a few days now and seem to be getting closer to a resolution (with help from the great users # SO). I'm using the CocoaAsyncSocket library to create a TCP socket connection to a Windows server.
The connection is being made in my appDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
socket = [[AsyncSocket alloc] initWithDelegate:self];
NSError *error = nil;
if (![socket connectToHost:#"199.5.83.63" onPort:11005 error:&error])
{
NSLog(#"Error connecting: %#", error);
}
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[tekMatrixViewController alloc] initWithNibName:#"tekMatrixViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
I have a connect method (part of the library) called onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port:
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
NSLog(#"connected :D");
}
This method is being called, as I can see the output from NSLOG and I am successfully connected. I can also see the connection is successful from the Windows machine (using log files).
I have also tested that another delegate method is being called as well:
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
NSLog(#"error - disconnecting");
// start reconnecting procedure here...
}
I have tested that the willDisconnectWithError method works by running my app in the simulator and then unplugging my ethernet cord from my laptop. Once I did this, I saw in my output the "error - disconnecting" string.
The big problem is, however, is that my delegate method (again, from the library) is not being invoked.
Delegate method not being invoked:
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length])];
NSString *msg = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
if(msg)
{
NSLog(#"RX:%#",msg);
}
else
{
NSLog(#"Fail");
}
}
I'm confident in my knowledge and understanding of how delegate methods work, but I still don't quite follow HOW they're INVOKED. To further complicate and cause confusion, one delegate method (onSocket: didConnectToHost port:) is being invoked, but the other (onSocket: didReadData tag:) is not being invoked. Unfortunately, this is only step one of my problem, but I'll have to get this issue fixed up before I get to the other issue.
Any help would be greatly appreciated. Thanks :D
From the AsyncSocket.h file:
/**
* Called when a socket has completed reading the requested data into memory.
* Not called if there is an error.
**/
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
My first guess is that you have an error and that's why your delegate method is not being called. Did you also implement the delegate method for handling errors?
/**
* In the event of an error, the socket is closed.
* You may call "unreadData" during this call-back to get the last bit of data off the socket.
* When connecting, this delegate method may be called
* before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:".
**/
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;
NOTE: Just because you are able to connect without error, doesn't mean that you are going to be able to read without an error occurring. The error argument that you pass into connectToHost:onPort:error: does not cover all error conditions.
EDIT: Could you post the portion of code where you call one of the "readData" methods on the socket? There may be something that is being overlooked there. If for example, no "readData" message is being sent to the socket, then that would explain why your delegate method is not being called.
EDIT: The onSocket:didReadData:withTag: method will only be called after you have invoked one of the following readData methods on the socket. For example:
// The readData and writeData methods won't block (they are asynchronous).
//
// When a read is complete the onSocket:didReadData:withTag: delegate method is called.
// When a write is complete the onSocket:didWriteDataWithTag: delegate method is called.
//
// You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.)
// If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method
// is called to optionally allow you to extend the timeout.
// Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect".
//
// The tag is for your convenience.
// You can use it as an array index, step number, state id, pointer, etc.
/**
* Reads the first available bytes that become available on the socket.
*
* If the timeout value is negative, the read operation will not use a timeout.
**/
- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;
I ran into a similar issue with the didReadData() method in my client app not being called after my server app sent set data via the [newSocket writeData:welcomData withTimout:-1 tag:1].
My problem was resolved once I inserted the following line within the didConnectToHost() method. [clientAsyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1.0 tag:0];
Now my client's didReadData() method is called appropriately whenever content is sent its way.

Subclassing UIApplication to override sendEvent causes crash

I'm trying subclass UIApplication to catch all touch event, this is used to see if user is afk or not. Anyway it works great first time you launch the application. If you put it in background and open it again 2 times then it crashes. I have no idea what causes this. I'm getting EXEC_BAD_ACCESS on [super sendEvent:event];
My Subclass MyUI:
#implementation MyUI
- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event]; // <-- EXEC_BAD_ACCESS
if (event.type == UIEventTypeTouches) {
UITouch *touch = [event allTouches].anyObject;
if (touch.phase == UITouchPhaseBegan) {
// Calling some methods
}
}
}
#end
Main.m
int main(int argc, char *argv[])
{
NSString* appClass = #"MyUI";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, appClass, nil);
[pool release];
return retVal;
}
Is there a reason the super class method is being called first? If you are intercepting, you should be calling it last.
That might be your problem. I also override sendEvent to intercept all events to my application and have no issues.
If you call the super method first it will pass it to all UIResponders that may eventually eat your event resulting in the EXEC_BAD_ACCESS. Furthermore as DavidNeiss suggests eliminate the lines below the super call. If you still receive the bad access signal its likely another view or controller down the line causing it. You'll need to stack trace to find out where it is.
To get exact reason for EXEC_BAD_ACCESS use nszombieenabled in your application.
This link will guide you for using it.
http://iosdevelopertips.com/debugging/tracking-down-exc_bad_access-errors-with-nszombieenabled.html
Dont understand what "afk" means.
Another approach might be to create a custom gesture recognizer. They (gesture recognizers) are supposed to filter through touch events before they are forwarded to the view as part of the normal touches event processing.
Just for simplicity's sake, I would put the #"MyUI" directly into the UIApplicationMain call.
The string is most likely your problem. It's outside of the NSAutoreleasePool, and that is just not done.
In addition, the name #"MyUI" hints at a view controller, not an AppDelegate class. Look into that.
[super sendEvent:event]; // <-- EXEC_BAD_ACCESS
means error is in your class.
For testing block
/*
- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event]; // <-- EXEC_BAD_ACCESS
if (event.type == UIEventTypeTouches) {
UITouch *touch = [event allTouches].anyObject;
if (touch.phase == UITouchPhaseBegan) {
// Calling some methods
}
}
}
*/
still you will get that error. Any time if you are getting error while override sendEvent
try to block all override method and check still you are getting that error or not specially for this line [super sendEvent:event];. I had also stuck with this error and figured out no mistake in this method. Mistake was found in applicationDidFinishLaunching. Always keep your code within try catch method
#try {
}
#catch (NSException *exception) {
NSLog(#"Exception => %#",exception);
}
This will help you figure out right problem.

Delegate functions not being called

Long time lurker, first time poster.
I'm making a ServerConnection module to make it a whole lot modular and easier but am having trouble getting the delegate called. I've seen a few more questions like this but none of the answers fixed my problem.
ServerConnection is set up as a protocol. So a ServerConnection object is created in Login.m which makes the call to the server and then add delegate methods in Login to handle if there's an error or if it's done, these are called by ServerConnection like below.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if( [self.delegate respondsToSelector:#selector(connectionDidFinish:)]) {
NSLog(#"DOES RESPOND");
[self.delegate connectionDidFinish:self];
} else {
NSLog(#"DOES NOT RESPOND");
}
self.connection = nil;
self.receivedData = nil;
}
It always "does not respond". I've tried the CFRunLoop trick (below) but it still doesn't work.
- (IBAction)processLogin:(id)sender {
// Hide the keyboard
[sender resignFirstResponder];
// Start new thread
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Acutally call the server
[self authenticate];
// Prevent the thread from exploding before we've got the data
CFRunLoopRun();
// End thread
[pool release];
}
I copied the Apple URLCache demo pretty heavily and have compared them both many times but can't find any discrepancies.
Any help would be greatly appreciated.
Here are the questions to ask:
Does your delegate respond to connectionDidFinishLoading:?
Does the signature match, i.e. it takes another object?
Is the delegate set at all or is it nil? (Check this in that very method)
If any of those are "NO", you will see "doesn't respond"... and all equally likely to happen in your application, but all are easy to figure out.