Fabric macOS exceptions not caught at times? - objective-c

Crashlytics shows me everything's going great, when in fact several people are experiencing crashes that aren't being reported - yet I do in fact see some crashes making their way through into Crashlytics. I can't understand what's going on.
I'm doing the usual I always have:
[Fabric with:#[[Crashlytics class], [Answers class]]];
first thing in applicationDidFinishLaunching. I also have:
// We need these flags in order to capture crashes more reliably
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"NSApplicationShowExceptions"]) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"NSApplicationShowExceptions"];
}
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"NSApplicationCrashOnExceptions"]) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"NSApplicationCrashOnExceptions"];
}
[[NSUserDefaults standardUserDefaults] synchronize];
directly before I register with Fabric. I also upload dSYMs every time and don't see any warnings from Fabric.
I've got a bunch of users crashing and sometimes they send us crash logs from either the machine or the window they're presented for crashes. Some people aren't seeing neither the crash window nor are they seeing crash logs accumulate in Console.app, nor am I seeing any crashes in Crashlytics - yet they have demonstrated countless times via videos that the app crashes soon after it launches.
What else can I do to ensure I get crashes reported always for a mac app?

This probably doesn't answer the question entirely, however it seems catching all exceptions / crashes on macOS is tricky (as mention by Fabric on their page). It doesn't help when a lot of the code it's crashing on is inlined C / C++ code. I don't think this is a Crashlytics issue as such, however it looks like a limitation where some crashes, including those force exit(..) call deep inside certain 3rd party libraries aren't really crashes and thus aren't caught.

Related

In iOS 9 the uitableview footer text alignment/spacing changed, what can I do?

Hei.
These two pictures below show what changed. Here's my code for it and the code didn't change.
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
if (section == 0) {
return #"If enabled, closing apps via the app switcher won't actually close the app itself.\n\nThis option is perfect to use with Fast Freeze.";
}
NSString *offDescription = #"OFF\nDisables the backgrounding capability completely. The app has to restart every time you close it.";
NSString *fastFreezeDescription = #"FAST FREEZE\nThis mode is similar to what 'Smart Close' by rpetrich did. Usually an app has up to 10 minutes to perform tasks in the background before it gets suspended in memory. Since this can be an unnecessary battery drain, Fast Freeze will suspend the app right after you close it.";
NSString *nativeDescription = #"NATIVE\nThis is Apple's built in way of backgrounding.";
NSString *unlimitedNativeDescription = #"UNLIMITED NATIVE\nThis background mode allows apps to execute background tasks for an unlimited period of time, so the app won't get suspended in memory after 10 minutes.";
NSString *foregroundDescription = #"FOREGROUND\nForeground tricks the system into thinking that the app wasn't closed and is still running in foreground. This is the perfect way to continue to listen to internet streams or videos while using another app.";
return [NSString stringWithFormat:#"\n%#\n\n%#\n\n%#\n\n%#\n\n%#", offDescription, fastFreezeDescription, nativeDescription, unlimitedNativeDescription, foregroundDescription];
}
Here are the screenshots:
This is the view before (iOS 8), notice that "\nOFF\nDisables ..." has the gap to the last UITableViewCell like it should be.
This is the view after (iOS 9), the gap is off. Too much space there.
So, does anyone know why this happens? If anyone has an fix or something, please tell me!
Thanks in advance!
This seems like an Apple's bug (iOS 9.0 - 9.1), the more lines footer has, the bigger misplacement gets.
You can even reproduce this in the storyboard using static table view.
I cound't find any workaround yet, the best advice I can give is to file a bug report to Apple.
Update
The bug in storyboard seems to be fixed in Xcode 7.2 beta 2. However this issue still persists when you run the app even on iOS 9.2 simulator.
Update 2
Narrowed down the reproduction of this bug. Basically something breaks after your app presents a table view section header. Check this repo for details.

Facebook Connect Login Dialog crashing app

Of the many problems I've been having with my current app, this is one of the most annoying.
In the simulator the login dialog works fine, however on a device it's just a frozen white box and the console prints the following:
void SendDelegateMessage(NSInvocation*): delegate
(webView:resource:willSendRequest:redirectResponse:fromDataSource:)
failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
I've looked this up but I'm still not sure what it means.
If I try switching
[self authorizeWithFBAppAuth:NO safariAuth:NO];
to
[self authorizeWithFBAppAuth:NO safariAuth:YES];
it switches to the safari app to verify but this somehow kills my app with an error which says ReturnNotPermittedKillClient.
Has anyone experienced a similar problem? On my last app it just worked without any of these issues, and as far as I can see I've done everything the same way this time. However this project was inherited from someone else so there may be underlying causes that I am not aware of.
Edit: Just tried moving the login request from didFinishLaunchingWithOptions to a point in the intro screen class where everything else has already been loaded, just in case it was a memory issue caused by too many tasks trying to run at the same time. This time the error message didn't appear, however the login box still remained white and then closed the app a few seconds later.
Edit2: Seems like it's simply a memory error. I changed all variables which I had previously released to be retained, which has fixed the problem on my 3GS. However on my iPad 1 the problem persists. Incidentally, when changing shouldAutorotateToInterfaceOrientation from using landscaperight to using landscaperight or landscapeleft, when I rotate the iPad I get a memory warning and then the same crash. In both cases there are no debug error messages other than the memory warning, and the app just closes down - there is no breakpoint etc to see where the issue lies.
if you are using the webview then we need to do this first b4 moving to next view .delegate = nil;
This might be what you want:
There are other branches of this in NSObject in the documentation.
Code:
[self performSelector: withObject: afterDelay: ]
The problem was simply down to memory. After changing the way it loads images, sounds etc the problem has gone away.

Upgrading app from IOS4 to IOS5

I have an IOS5 app which uses following function
[self.presentingViewController dismissModalViewControllerAnimated:YES];
and who works perfectly on IOS4 but suddenly I discovered that this function doesn't exists on IOS5 so I had to use this other equivalent one
[self.parentViewController dismissModalViewControllerAnimated:YES]
Now I've got the following issue: IOS4 users are not able to install my app due to this non existing function in IOS4 and what is even worse, the app is available on Apple's App Store but is only functional of IOS5 users. Another related issue us that the app suddenly stopped working on iPads equipped with Wifi, those connected to 3G networks operate normal.
Is there anything I missed trying to compile this new app version?
Thanks in advance!
You can check for existence of the property like this:
if([self respondsToSelector:#selector(presentingViewController)])
[self.presentingViewController dismissModalViewControllerAnimated:YES];
else
[self.parentViewController dismissModalViewControllerAnimated:YES];
Code it this way:
if ([self respondsToSelector:#selector(parentViewController)])
[self.parentViewController ...];
else
[self.presentingViewController ...];
(This is uncompiled, untested, etc.)
The point is that you can (and should) test for capabilities, and then act accordingly. In this case, if the iOS5 method is available, use that one. If not, use the old one, which also means its a pre-iOS5 device.
The way to go is twofold:
compiling your app against the latest SDK version, but also set the deployment target to the oldest version that you want to support; this will ensure that the app is listed properly in the App Store;
checking before using any method/feature that is only available on a later version; this will ensure that you app will not crash and can be done by means of conditional compilation, e.g.:
k
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
if ([[UIApplication sharedApplication] respondsToSelector:#selector(beginBackgroundTaskWithExpirationHandler:)])
{
UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] eginBackgroundTaskWithExpirationHandler:^{}];
// Perform work that should be allowed to continue in background
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}
#endif
this is quite convoluted if you have to do it in many places. You may have a look at this very good post to learn how to improve upon that example.
I have built a category that add presentingViewController on iOS 4.
(It disables itself on iOS 5.)
It works seamlessly; Just include 2 files.
Please see backward-modal.
I hope this benefits you as much as it does to me; It makes your code more clean!

iOS settings toggle switch works the first time but not again

I am using the iPad settings app to change some button sounds and a background image. It all works well and the settings are maintained from one app launch to another in the simulator. Now I have implemented a toggle switch to either set sets of sounds off or on. When the app launches, whatever state the switch is in, it works; e.g. if the "Alert Sounds" switch is OFF the alert sounds are silent and if I change it to ON the sounds will start working. However, if I turn the switch back OFF the sounds still keep working. However, if the state is ON when the app launches, the sounds work, but will not be silenced when the switch is set to OFF.
Note that this is different than the settings not taking effect until a second round of settings. That was a previous problem I solved (thanks to stack overflow) by using:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults] synchronize];
}
I have methods named:
- (void)defaultsChanged:(NSNotification *)NSUserDefaultsDidChangeNotification
(which is called when the notification is sent)
and
-(void)setValuesFromPreferences
(which is called in ViewDidLoad)
The logic looks like this in both:
// Set alert sounds from preferences
NSString *alertSoundPreference = [userDefaults stringForKey:kAlertSound];
BOOL alertSoundEnabled = [userDefaults boolForKey:kAlertSoundEnabled];
if (alertSoundEnabled)
{
// Create the URLs for the alert audio files
// Store the alert sound URLs as a CFURLRef instances
// Create system sound objects representing the alert sound files
}
I do not have an else, because I assume that no sound resources will be specified if alertSoundEnabled is NO.
I have searched for explanations and tutorials that mention this problem but have not found any yet, so I'm asking here. Thanks for any suggestions.
viewDidLoad is not necessarily called when the app becomes active again (nor does viewWill/DidAppear, IIRC), as the whole point of iOS 4+ multitasking is to prevent such loading/unloading and recreation of objects on app-switching.
If I had to guess, the sounds are already allocated when the user had the switch ON at original launch/viewDidLoad; however, if your code does nothing to explicitly disassociate them when it loads back up, they would continue playing, as they are all already set up.
As such, I'd try adding an else clause that (upon alertSoundEnabled == NO) destroys your system sound objects.

Using iPodMusicPlayer without giving control to iPod in background

I'm developing an app with a very specific focus on shuffling songs within a selected playlist. When the app launches, it lists all the user's playlists, and then when one is selected it loads it into my music player view and get's going. I'm using an MPMusicPlayerController iPodMusicPlayer to handle doing this because I'm pretty new at iOS development and it handles backgrounding and everything nice and easily for me. I want music to continue playing in the background and I like how whatever I change within my app is also reflected in the iPod app. However, I don't want the user to be able to change things in the iPod app and then return to mine. Since my app is all about shuffling, the user could easily go into iPod and disable shuffle, then come back to my app and the experience is ruined. I also don't want them to change the playlist from within iPod.
Can anyone help me think of a way to accomplish this? Play/pause/skip/prev/volume is no problem from within iPod (I want that to be possible), but I don't want changing the song queue to be possible. Is there a way I could add a handler in my app that catches if the user changed something while my app was in the background (and if so, stop music and reset my app to the initial screen)? I'd really appreciate any suggestions. I'm hoping something like this is possible before I venture into using AVPlayerQueue or the like (as a side note, can you play DRM'd files with AVPlayerQueue?).
What I would do is set a bool when backgrounded:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setBool:YES forKey:#"BACKGROUNDED"];
Then, in your handler for the MPMusicPlayerControllerNowPlayingItemDidChangeNotification that you should be implementing so that you have that control, do the following:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if ([prefs boolForKey:#"BACKGROUNDED"]) {
[prefs setBool:NO forKey:#"BACKGROUNDED"];
exit(0);
}
It might be too abrupt, depending on when it checks this code (I don't know when it does in your project) but that should accomplish your goal. exit(0) is the way to terminate your app without throwing an exception. Is that helpful?