How can I intercept fatal exceptions? - ios

I want to integrate in my iPad application a way to monitor the user activity and especially the exceptions that occurred and triggered the application to stop, something like the bug report of Apple but for the mobile clients.
I tried to encapsulate the main action (main.m) between #try and #catch blocks, but the exception is not thrown until there, and I just can't add such blocks everywhere in my code. Neither the delegate method applicationWillTerminate is not called, the application is just brutally stopped without any notification.
Any ideas on this ?

It works for me in main.m
int main(int argc, char *argv[]) {
#autoreleasepool {
int retVal = 0;
#try {
retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
#catch (NSException *exception) {
NSLog(#"Exception: %#", exception);
[exception raise];
}
return retVal;
}
}
P.S.
Another tricky way : EXC_BAD_ACCESS automatic handling
And example of NSUncaughtExceptionHandler

Related

Why does modern Xcode generate projects with UIApplicationMain outside of autorelease pool?

If I remember correctly, back in the days Xcode used to generate the main function something like this (at least for iOS applications):
int main(int argc, char * argv[]) {
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]);
}
}
I.e. UIApplicationMain function was wrapped inside of #autoreleasepool. However I noticed that currently Xcode no longer does that:
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
#autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
So, UIApplicationMain is outside of the autorelease pool by default nowadays. Is there any official changelog/paper that explains why the latter implementation is now preferred over the former one?

MIDINetworkConnection causing crashing errors

I am experiencing frequent crashing that I believe is related to this method of checking the number of MIDINetwork Sessions.
- (NSString*) describeConnections {
NSMutableArray* connections = [NSMutableArray arrayWithCapacity:1000];
for (MIDINetworkConnection* connection in [[MIDINetworkSession defaultSession] connections]) {
[connections addObject:[[connection host] name]];
}
if ([connections count] > 0) {
return [connections componentsJoinedByString:#", "];
}
else
return #"(Not connected)";
}
When the app crashes it stops on the line
for (MIDINetworkConnection* connection in [[MIDINetworkSession defaultSession] connections])
The error I am getting is
Thread 1: EXC_BAD_ACCESS(code=EXC_1386_GPFLT)
In the debugger it shows
_impl _MIDINetworkConnectionImpl * NULL
I have tried to prevent the crashing by checking if MIDINetworkSession is NULL before looping through the connections but that hasn't worked. Occasionally when xcode crashes it will stop at
int main(int argc, char *argv[])
{
#autoreleasepool {
int retVal = UIApplicationMain(argc, argv, nil, nil);
return retVal;
}
}
Can anyone offer a guess as to what's happening?
It seems that connections contain NULL, in some case the system dealloc the connections.But in the set, it cannot use the NULL to be elements, so you should check the connections or use the try catch to get the exception.

App crashes after I run the script

I'm trying to run my tests scripts on different device(iPhone, iPad, Air), but all the same. When i push Play button ,app started and crashed. And my scripts can not be executed.(Simply stopped). Please tell me why!?I use UI automation tool.
Thanks!
in main.m in main function use this code,
#try {
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([RRAppDelegate class]));
}
}
#catch (NSException *exception) {
NSLog( #"There is some error === %#",[NSString stringWithFormat:#"%#",exception]);
}
It will show u the err reason. I haven't 50 reputation, so i am unable to comment.

Why can [SomeClass class] return null in main.m

I am trying to make an iOS app without using xibs or storyboards. So my main.m
looks like this:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
[pool release];
return retVal;
}
If I check value of [AppDelegate class] it is (null).
So the question is, why?
Also if i check [NSString class] or other class from standard library it performs normally.
I thought that file is not in Compile sources list, but it's there. This problem only occurs in one project.
Check if you have initialized assigned some controller to your window's root controller in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions.
Check out this answer.

Why does Xcode 4.2 use #autoreleasepool in main.m instead of NSAutoreleasePool?

I've noticed that there is a different way in Xcode 4.2 to start the main function:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([PlistAppDelegate class]));
}
}
and
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Does anybody know the difference between those two?
The first one is using ARC, which is implemented in iOS5 and above to handle memory management for you.
On the second one, you're managing your own memory and creating an autorelease pool to handle every autorelease that happens inside your main function.
So after reading a bit on what's new on Obj-C with iOS5 it appears that the:
#autoreleasepool {
//some code
}
works the same as
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// some code
[pool release];
with the difference that the last one would throw an error on ARC.
EDIT:
The first one is using ARC or not.

Resources