I'm trying to use Parse analytics in my app to track errors, but when the trackEvent method is called, i receive an EXC_BAD_ACCESS.
I use the code from Parse documentation
NSString *codeString = [NSString stringWithFormat:#"%d", [error code]];
[PFAnalytics trackEvent:#"error" dimensions:#{ #"code": codeString }];
I though i was doing something wrong with the dimensions NSDictionnary, so i tried:
[PFAnalytics trackEvent:#"error"];
But I'm still receiving the same signal. I know that EXC_BAD_ACCESS is thrown as a result of an illegal memory access, but in that case i'm just calling static method with a simple string as a parameter, so I don't know what i'm doing wrong.
Have you encountered the EXC_BAD_ACCESS in that case, and how did you deal with it ?
Related
I have 10 Classes in my project,At present i was placing try catch block in each and every method in all 10 classes to catch the exception which seems to be a bulky code.
Now i want to maintain a Single try catch block through out the project, means if any exception occurred in all my 10 classes that should be catched by try catch block.
Is it possible to do like this…
NSArray *arr=[[d1 objectForKey:#"Time"] componentsSeparatedByString:#" "];
NSArray *arr1=[[arr objectAtIndex:1] componentsSeparatedByString:#":"];
Here my object “Time” is coming from the Service.
so if the object is empty it may cause to
Array out of index Exception.
I know which i can solve by comparing the length of String.So, if suppose if forgot to compare length in some cases.
In that case i want to catch the exception and i want to post it to my server.
#catch (NSException *exception) {
NSString *stacktrace=[exception.reason stringByReplacingOccurrencesOfString:#"<" withString:#""];
stacktrace=[stacktrace stringByReplacingOccurrencesOfString:#">" withString:#""];
// NSString *strClass = NSStringFromClass([self class]);
NSString *strClass = [NSString stringWithFormat:#"%# : %#",NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
Item* myStore = [Item sharedStore];
myStore.strErrorDescription=exception.name;
myStore.strErrorStack=stacktrace;
myStore.strErrorPageName=strClass;
[myStore PostError];// To Post the exception to My server.
ErrorView *errorView=[[ErrorView alloc]initWithNibName:#"ErrorView" bundle:nil]; [self presentViewController: errorView animated:NO completion:nil];
}
Thank you.
The real answer here is You're Doing It Wrong.
Exceptions in Objective-C are different from those in other languages like Java or Ruby. In particular, they tend to be "non-recoverable", meaning that once some code throws an exception, a number of assumptions about the state of memory allocations, etc become false, and your program is probably on its way to crashing.
The overall approach Apple recommends is to treat exceptions as a symptom of a programmer error. The example you give is the same one they do: neglecting to check the length of an NSArray. You should aim to find and eliminate those during your development process; the best way to do that is probably to let your program crash as a result of the exception, then find and fix the offending code.
I have a code for fetching json. It works perfectly fine, when my device is connected to internet, but it crashes if there is no internet connection.
I have surrounded that particular line of code with try / catch block, but it doesn't seem to do the trick.
Of course, I can do a workaround, and first check if there is internet connection and then call the method I need, but I want to understand this.
Why #catch isn't triggered in this case, and what to do to handle this exception in this case?
Here is the code:
#try {
NSError *error;
NSMutableDictionary* json = [NSJSONSerialization
JSONObjectWithData:_jsonData
options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
error:&error];
...
#catch (NSException *exception) {
[_indicator stopAnimating];
_indicator.hidden = YES;
[self popUp];
}
So, the exception occurs when trying to populate json dictionary.
Your JSON data _jsonData seems to be obtained before try~catch block, and then the source of the issue should be out of the block. Then you need to find out where the data is obtained from the internet, and install the try~catch block at there.
I'm trying to test the behavior of my app when connection fails. I am testing on an iPad with wifi turned off. When Restkit attempts a web service call, I get the following error:
CPL[7713:6203] E restkit.network:RKRequest.m:545 Failed to send request to https://xxxxxxxx/APNS_WebService/rest/operations/initializeDevice?deviceID=c4a17f855d3cc824b174b71908480d4e505ebfb221cb4643da9270a07344c367 due to unreachable network.
The problem is that I would like to handle this situation in a delegate callback method, but none of the delegate methods are being called. I have set the delegate on the request, and have requestDidFailLoadWithError, requestDidCancelLoad, requestDidTimeout, and objectLoaderDidFailWithError implemented. None of these are called.
Why aren't my delegates being called?
EDIT: After setting a breakpoint inside RKRequest.m, I see that the following line is in fact being executed:
[self performSelector:#selector(didFailLoadWithError:) withObject:error afterDelay:0];
However, my delegate methods are not getting called.
Here's where I set the delegate:
request = [client requestWithResourcePath:[NSString stringWithFormat:#"/initializeDevice?deviceID=%#",deviceID]];
request.delegate=self;
[request sendAsynchronously];
EDIT 2: Actually, the line in RKRequest.m that I posted above is just calling another method in RKRequest, except that it's not. Putting a breakpoint in didFailLoadWithError shows that this code is never reached. I don't get why that's not working.
Changing the performSelector to a regular method call appears on the surface to give me the behavior I'm looking for. Is this going to break anything? I guess I'm not sure why performSelector is being used to call a method in the same class.
EDIT 3: As requested, here's my delegate method:
-(void)request:(RKRequest *)request didFailLoadWithError:(NSError *)error{
NSLog(error.domain);
NSLog([NSString stringWithFormat:#"%d",error.code]);
NSLog(error.localizedDescription);
NSLog(error.localizedFailureReason);
[request reset];
[request send];
}
EDIT:
Actually, the line in RKRequest.m that I posted above is just calling another method in RKRequest, except that it's not. Putting a breakpoint in didFailLoadWithError shows that this code is never reached. I don't get why that's not working.
This is really strange. I would try doing a full clean of the project and rebuild.
As to what entails a direct call instead of using performSelector, you can see that afterDelay:
[self performSelector:#selector(didFailLoadWithError:) withObject:error afterDelay:0];
this will make the didFailLoadWithError: method be called at the next iteration of the run loop. I would keep this way of calling it.
You could try, though, with this alternative:
dispatch_async(dispatch_get_current_queue(), ^() {
[self didFailLoadWithError:error]; } );
I would suggest setting a breakpoint inside of the RestKit method you are using (I suppose sendAsynchronously) and check what happens. If you look into the method definition, the call to the delegate is effectively there:
} else {
self.loading = YES;
RKLogError(#"Failed to send request to %# due to unreachable network. Reachability observer = %#", [[self URL] absoluteString], self.reachabilityObserver);
NSString* errorMessage = [NSString stringWithFormat:#"The client is unable to contact the resource at %#", [[self URL] absoluteString]];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
errorMessage, NSLocalizedDescriptionKey,
nil];
NSError* error = [NSError errorWithDomain:RKErrorDomain code:RKRequestBaseURLOfflineError userInfo:userInfo];
[self performSelector:#selector(didFailLoadWithError:) withObject:error afterDelay:0];
}
I know in Android, there is a pretty reliable built-in system for notifying me of crashes that happen. They almost immediately write the stack trace and some other info into a Google doc. it works tremendously well.
I started researching the same thing for ios, and I am not finding anything similar that is equally effective. I read this article: Xcode storyboard: Why does the iPad storyboard show iPhone sized views?
but I am not sure if this is still the case. Could anyone recommend me what to use for crash reports that happen on user devices?
Thanks!
I'm using Flurry with an uncaughtExceptionHandler and GTMStackTrace
The exception handler can look like this:
void uncaughtExceptionHandler(NSException *exception)
{
#try
{
NSString *fullBacktrace = GTMSBStackTraceFromException(exception);
NSMutableString *backtrace = [NSMutableString stringWithUTF8String:""];
NSArray *backtraceArray = [fullBacktrace componentsSeparatedByString:#"\n"];
for (id entry in backtraceArray)
{
NSRange testRange = [entry rangeOfString:[[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleName"]];
if (testRange.length)
{
[backtrace appendString:entry];
}
}
NSCharacterSet *whitespaces = [NSCharacterSet whitespaceCharacterSet];
NSPredicate *noEmptyStrings = [NSPredicate predicateWithFormat:#"SELF != ''"];
NSArray *parts = [backtrace componentsSeparatedByCharactersInSet:whitespaces];
NSArray *filteredArray = [parts filteredArrayUsingPredicate:noEmptyStrings];
NSString *strippedBacktrace = [filteredArray componentsJoinedByString:#" "];
[FlurryAnalytics logError:#"uncaughtExceptionHandler"
message:[NSString stringWithFormat:#"%#", strippedBacktrace ? strippedBacktrace : #"no matching backtrace"]
exception:exception];
}
#catch (NSException *exception)
{
NSLog(#"whoa! could not handle uncaught exception!");
[FlurryAnalytics logError:#"uncaughtExceptionHandler"
message:#"no matching backtrace"
exception:exception];
}
}
Testflight has a good crash log too.
What you can do is create a new uncaught exception handler, then register it via NSSetUncaughtExceptionHandler. That way, each crash can be intercepted just before the kill, and you can log it / save it somewhere to upload.
(I've personally used the method described in this link : http://cocoawithlove.com/2010/05/handling-unhandled-exceptions-and.html)
Setting an uncaughtexception handler will only give you a subset of crash reports, and also the details of the reports you get that way are very limited. You don't get stack traces of all threads, you don't get the stacktrace of the exception where the crash really happened, and you don't get the line numbers of your code where the crash happened. In addition you don't get any crash reports caused by signal handlers.
In addition you should NOT run any objective-C code once a crash occurs since it is not async-safe. See this article for more information about it: Reliable Crash Reporting
If posted some more details on what you can do as answers to the following questions: Crash analytics and reporting for iOS and iOS crash log catch, debug info.. Catch and send via email to the Dev team
I am having this horrible crash out of my application that I have been trying to resolve for several days now. The code is an NSURLRequest to send a request to a web-service. I already use the web-service in production and I simply added this new service request. I finally added #try ... #catch around the offending code and it still crashes the application and does not "catch" anything.
How do I debug this?
I have used code inspection, including a peer review.
The code is like this ... where "httpClient" is an NSObject with:
id _delegateConnection;
id _delegateReceiver;
NSURLConnection *connection;
NSMutableURLRequest *urlServiceRequest;
NSMutableString *bodyRequest;
NSHTTPURLResponse *httpResponse;
NSMutableData *responseData;
NSError *error;
#try {
[httpClient setDelegateReceiver: self];
[httpClient buildRequest: dictParameters];
[httpClient executeRequest];
}
#catch (NSException *exception) {
NSLog(#"%s: %#", __FUNCTION__, exception);
}
#finally {
// Add code here ...
}
I found the problem and it was through good-fortune and code inspection in a different part of the code ("where the light was better" :)
As it turns out, I have a dictionary of parameters that get written to a JSON string, added to the HTTP body of the urlServiceRequest object listed in my sample code. What I finally stumbled upon was that the parameter container (NSObject, not NSDictionary) was not "retained", therefore it was probably "autoreleased", while still referenced within my buildRequest method, by the posting of the urlServiceRequest.
Poor memory management on my part led me astray in my troubleshooting.