NSUserDefault not Saving If Followed by a Delegate - ios

I am finding that if I execute a custom delegate method right after saving to NSUserDefaults, the data is not saved and the following error is displayed:
The operation couldn’t be completed. (OSStatus error -10875.)
The above error shows under iOS 8 but does NOT show under iOS 7. However, the results (the data not saving) is common to both versions. iOS 7 just doesn't show an error has occurred. Also, this is running on a simulator.
This issue only occurs when I call a custom delegate after writing the data. If I remove the custom delegate, the data is written with no issues.
The code is as follows:
[self.prefs setObject:self.secondsLabel.text forKey:#"timer"];
[self.prefs setInteger:self.questionTypeControl.selectedSegmentIndex forKey:#"type"];
[self.prefs setBool:self.speedSwitch.on forKey:#"speed"];
[self.prefs setBool:self.mixupSwitch.on forKey:#"switch"];
[self.prefs synchronize];
[self._delegate setupStatus:configChanged withVC:self];
[self dismissViewControllerAnimated:YES completion:nil];
As "synchronize" returns a BOOL I did do a check and did find that it was returning TRUE so the data should be saved, but again it is not. If I comment out the delegate line, the data is saved appropriately.
The delegate is firing a method in the prior VC. I put a breakpoint on the first line of that method but the error had already occurred. This makes me believe that the issue is simply the act of calling the method. Of interest, if instead of using a delegate I use an NSNotification, the problem doesn't present itself.
Why would calling a delegate cause the error and the inability to save the data?
Update: I did run it on an actual device (iPad running iOS 8.1). I still get the exact same error as mentioned above, however, the data DOES actually save. So the sim and device produce the same error but on the sim it won't save and on the device it will. Again this is only if the delegate is present.

Related

WatchKit extension crash: "Program ended with exit code: 0"

For people wanting to reply quickly without reading the post: I am not hitting any memory limits. Read the whole post for details.
My WatchKit extension cannot properly function without the user first being "onboarded" through the phone app. Onboarding is where the user must accept the permissions that we require, so it's very crucial.
On my WatchKit extension, I wanted to display a simple warning for users who had not finished onboarding within our phone app yet.
As such, I thought I'd get the status of onboarding from the phone in two ways:
When the user opens the app/the app is activated (I use the willActivate method to detect this)
When the app finishes onboarding it sends a message to the watch of its completion (if the extension is reachable, of course)
Both of these combined would ensure that the status of onboarding is always kept in sync with the watch.
I wrote the first possibility in, utilizing reply handlers to exchange the information. It worked just fine, without any troubles. The warning telling the user to complete disappears, the extension does not crash, and all is well.
I then wrote in the second possibility, of the extension being reachable when the user finishes onboarding (with the phone then directly sending the companion the new status of onboarding). My extension crashes when it receives this message, and I am stuck with this odd error.
Program ended with exit code: 0
My extension does not even get a chance to handle the new onboarding status, the extension just quits and the above error is given to me.
I am not hitting any sort of memory limit. I have read the technical Q&A which describes what a memory usage limit error looks like, and I don't receive any sort of output like that whatsoever. As well, before the extension should receive the message, this is what my memory consumption looks like.
I have monitored the memory consumption of the extension right after finishing onboarding, and I see not a single spike indicating that I've gone over any kind of threshold.
I have tried going line by line over the code which manages the onboarding error, and I cannot find a single reason that it would crash with this error. Especially since the reply handler method of fetching the onboarding status works so reliably.
Here is the code of how I'm sending the message to the watch.
- (void)sendOnboardingStatusToWatch {
if(self.connected){
[self.session sendMessage:#{
LMAppleWatchCommunicationKey: LMAppleWatchCommunicationKeyOnboardingComplete,
LMAppleWatchCommunicationKeyOnboardingComplete: #(LMMusicPlayer.onboardingComplete)
}
replyHandler:nil
errorHandler:^(NSError * _Nonnull error) {
NSLog(#"Error sending onboarding status: %#", error);
}];
}
}
(All LMAppleWatchCommunicationKeys are simply #define'd keys with exactly their key as the string value. ie. #define LMAppleWatchCommunicationKey #"LMAppleWatchCommunicationKey")
Even though it's never called by the extension, here is the exact receiving code of the extension which handles the incoming data, if it helps.
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message {
NSString *key = [message objectForKey:LMAppleWatchCommunicationKey];
if([key isEqualToString:LMAppleWatchCommunicationKeyOnboardingComplete]){
BOOL newOnboardingStatus = [message objectForKey:LMAppleWatchCommunicationKeyOnboardingComplete];
[[NSUserDefaults standardUserDefaults] setBool:newOnboardingStatus
forKey:LMAppleWatchCommunicationKeyOnboardingComplete];
dispatch_async(dispatch_get_main_queue(), ^{
for(id<LMWCompanionBridgeDelegate> delegate in self.delegates){
if([delegate respondsToSelector:#selector(onboardingCompleteStatusChanged:)]){
[delegate onboardingCompleteStatusChanged:newOnboardingStatus];
}
}
});
}
}
Before including this onboarding-related code, my WatchKit extension was tested by over 100 people, without any troubles. I am using the exact same custom error dialogue that I was using before, just with a different string. I cannot for the life of me figure out what is causing this crash, and the ambiguity of it has given me very little to work with.
Any help would be greatly appreciated. Thank you very much for taking your time to read my post.
Edit: I just tried creating a symbolic breakpoint for exit(), which is never hit. If I call exit() myself, it calls the breakpoint, so I know the breakpoint itself is working.

Objective c Thread 1 signal SIGSTOP app crashes

I'm trying to track down an error that appears to be definitely a timing issue. I have an application that uses a Universal Framework. When the process is complete in the framework an NSNotification is sent back to the application. We have recently added a third party framework to our framework. Now, while the methods for the third party framework are being executed, as execution returns to our framework I receive the following error in the Console Output:
Assertion failed: (exclusive), function assert_locked, file ../dep/include/boost/boost_1_55_0/boost/thread/pthread/shared_mutex.hpp, line 51.
But I'm not sure that is the ultimate issue, because our framework continues to execute and the NSNotification is sent back to the application. Right after the Notification is sent and execution returns to the calling method (or the method call) in our framework I see a warning on the executing thread. Then, execution continues back to the original calling method and the warning goes away.
Here's the weird part. If I step through the code very slowly, it might just work. If I'm not slow enough I get the SIGSTOP and the code never returns to the UI. If I'm too fast, I get a SIGABRT.
I've been trying to find the exact issue using Instuments. This answer to a similar question backed up my suspicion that this is a timing issue. I think the boost assert_locked Assertion might have something to do with this.
My code is pretty boring but I know you want to see it, so here it is:
- (void)generateImageTemplates:(UIImage *)src
{
int result = 0;
cv::Mat image = *(cv::Mat*)[self cvMatFromUIImage:src];
user = IEngine_InitUser();
int userID=0;
result = IEngine_AddFingerprintRAW(user, UNKNOWN, image.data, image.size().width, image.size().height);
result = IEngine_RegisterUser(user, &userID);
[[NSNotificationCenter defaultCenter] postNotificationName:#"InnovatricsComplete" object:self];
}
If you're wondering what result is, it's an error code. So far these have all come back equal to 0. Meaning no errors. I'll work on handling these errors once I can get a successful return to the UI without crashing.
Control returns to the method call:
- (void)generateImageTemplates:(UIImage *)processedImage
{
[self.captureCommand generateImageTemplates:processedImage];
}
Control returns to the method call in the application View Controller:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
[self clearPressed:self.clearButton];
} else {
[self.cameraVC generateImageTemplates:self.processedImage];
}
}
Finally, the NSNotification callback code:
- (void)onInnovatricsComplete:(NSNotification *)note
{
[self.cameraVC willMoveToParentViewController:nil];
[self.cameraVC.view removeFromSuperview];
[self.cameraVC removeFromParentViewController];
}
I warned you it was pretty boring!
I'm completely stumped! Though I continue to surf the internet for clues, is there anybody out there who can help me resolve this issue?
Thank you.
Here are some screenshots (in reverse order):
look at NSUinteger’s answer in How to know where crash for postNotificationName:object:userInfo
the listener might be deallocated before it recieves the notification.

Getting "malloc: *** error: incorrect checksum for freed object" inconsistently

The full error is:
app(85540,0x38661a8) malloc: *** error for object 0x11214f84:
incorrect checksum for freed object - object was probably modified after being freed.
So I'm getting something that is quite hard to replicate and I suspect is has something to do with the way I have my block set up. What I'm trying to get is the current online status of gamers on Xbox Live, so I allocate 2 NSMutuableDictionaries in viewDidLoad. onlinePlayers is for holding the online status values of the gamers so it's not checked over and over again in cellForRowAtIndexPath when scrolling up and down. checkedPlayers is to prevent multiple calls going out trying to get the status of the same player. Anyway, if I keep launching the simulator over and over again, it will be fine 29/30 launches, but it always crashes at least once on launch with the above error when I'm trying to set the online status value for a gamer:
NSString* gamertag = cell.gamerTagLabel.text;
if (![_checkedPlayers containsObject:gamertag]) {
[_checkedPlayers addObject:gamertag];
[Utilities processJSONDataWithGamertag:gamertag andBlock:^(NSData *jsonData) {
id onlineStatus;
NSDictionary *allXboxAttributes = [Utilities returnJSONObject:jsonData];
// Get current Xbox Live Data
if ([allXboxAttributes objectForKey:#"data"]) {
NSDictionary *dataXboxAttributes = [allXboxAttributes objectForKey:#"data"];
onlineStatus = [dataXboxAttributes objectForKey:#"online"];
// Crashes on the line below
[_onlinePlayers setObject:onlineStatus forKey:gamertag];
// Return to main thread and update online status
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
}
If it helps for some reason, the value being returned from dataXboxAttributes is a BOOL. Any help would be much appreciated. Thanks!
You are getting the error in that method but the problem might be elsewhere.
To find the source of the problem, in XCode go to Product > Scheme > Edit Scheme, and under Diagnostics tab enable all the Malloc settings and Guard Malloc.
With that, run your application again, and XCode will stop at the line causing the problem.
from your code it looks like the completion block of processJSON isnt always on the main thread, synchronize access to onlinePlayers.
#synchronized will do I guess

Suppress RestKit Error Message

Using RestKit 0.20.x I am firing off a series of API calls on a particular view. If the user sends the app to the background I am cancelling ALL API calls using the following statement in the app delegate
- (void)applicationDidEnterBackground:(UIApplication *)application{
[self.weatherManager.restKitManager.operationQueue cancelAllOperations];
}
When the app returns from the background a UIAlert is visible with the following message:
The operation could not be completed. (org.restkit.RestKit.ErrorDomain error 2).
I don't want the user to have to see or dismiss this message upon return but am having trouble figuring out where/how to suppress this message.
Initially I was avoiding the use of cancelAllObjectRequestOperationsWithMethod: matchingPathPattern: because I had found a post on Google Groups from Blake Watters suggesting the use of the cancelAllOperations method on the operation queue which did not require a pathPattern
However If I use
[self.weatherManager.restKitManager cancelAllObjectRequestOperationsWithMethod:RKRequestMethodAny matchingPathPattern:#"/"];
by specifying a path pattern of just a "/" this seems to do the trick.

iOS App crashes on exit, how to debug?

My app crashes when I quit it(not press home button and go to background), I guess the problem is that some objects released in viewDidUnload, are released again in dealloc, but I'm not sure. As my code has more than 10000 lines, is there any tool or method so I can quickly pinpoint the bug? Or is it caused by something else rather than one object being released twice?
Thanks!
Here is a screenshot of left pane:
Also, I tried to log messages in viewDidUnload and dealloc, but did not see any error message.
- (void)viewDidUnload {
print "viewDidUnload 1";
// actual method body
print "viewDidUnload 2";
}
the same for dealloc.
Edit 2:
My app uses Core Data, so is there anything I need to manually finalize on exit for Core Data(or it will crash)?
Test it on a real device - if the app crashes, a crash log will be generated. It will be available in the Organizer Window of XCode in Device Logs section corresponding to your device.
That log will give you the call stack of the crash, probably narrowing the places you need to search.
It's hard to say if you have not posted any code.
Do you have any crash logs?
How are you releasing in viewDidUnload?
[_mayVar release]; // 1. on its own this will most likely cause a crash
[_mayVar release]; _myVar = nil; // 2. This is better as sets the pointer to nil
self.myVar = nil; // 3. If you use properties this is easier than line 2
i have the same problem and running it on a real device showed that it crashes in FlurryAnalytics. Do you use that?
I had to remove it completely from the project (not only not starting the session!) to fix this crash.

Resources