Cocoa-Touch: performSelectorOnMainThread: weird behavior + crash - iphone

I have a situation where I'm lazy loading images from the www.
It's a list of items, when one item is tapped, a detail view is pushed to a nav controller.
In that detail view the item has an image, which first is a default image, and I want to start loading it's image from a URL.
So what I do is create an object which once initialized detaches a new thread which in turn loads the content and afterwards notifies my view that the data is loaded:
// in MyLoader:
- (MyLoader *)initWithUrl:(NSURL *)url requester:(id)requester {
self.url = url;
self.requester = requester; // both are nonatomic, retain properties
[self performSelectorInBackground:#selector(loadIt) withObject:nil];
}
- (void)loadIt {
NSAutoreleasePool *arp = [[NSAutoreleasePool alloc] init];
NSData *data = [NSData dataWithContentsOfURL:url];
[requester performSelectorOnMainThread:#selector(dataReady) withObject:data waitUntilDone:YES;
[arp release];
}
// in MyRequester:
- (void)somewhere {
MyLoader *loader = [[[MyLoader] alloc] initWithUrl:someUrl requester:self] autorelease];
// then I retain loader somewhere, it's more complicated but I have verified that it's properly retained.
}
A few notes:
First I thought there might be a problem with some of the variables. I put a breakpoint right before performSelectorOnMainThread and confirmed that data and requester were both OK.
Then I thought it was caused by passing the NSData across the threads, so I changed withObject:nil. It still crashes.
When I further investigated, the crash was very strange. I specified waitUntilDone:YES, I've placed a breakpoint in the requester's dataReady. But the performSelectorOnMainThread call returns (it reaches the breakpoint after it) while not reaching the breakpoint inside dataReady. BTW, - (void)dataReady:(NSData*)'s body for now only contains int x = 1; (to place a breakpoint on). Also, I've tried setting waitUntilDone:NO, it still crashes.
The selector isn't performed (the breakpoint is not reached), but the crash happens a short while after the call.
Does anyone have any idea what's wrong?
This is obvious, but just to be clear, if I just comment out the [requester performSelectorOnMainThread... part, it doesn't crash.
Also, here's a stack trace, but it's not helpful at all.
#0 0x00a71004 in ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___ ()
#1 0x93436e3b in objc_exception_throw ()
#2 0x0028aca6 in __NSThreadPerformPerform ()
#3 0x00a098e1 in CFRunLoopRunSpecific ()
#4 0x00a08c48 in CFRunLoopRunInMode ()
#5 0x0005a78d in GSEventRunModal ()
#6 0x0005a852 in GSEventRun ()
#7 0x0168a003 in UIApplicationMain ()
#8 0x000028d4 in main (argc=1, argv=0xbffff100) at /Users/myName/Document/appName/main.m:14

You have:
[requester performSelectorOnMainThread:#selector(dataReady) withObject:data waitUntilDone:YES;
should be:
[requester performSelectorOnMainThread:#selector(dataReady:) withObject:data waitUntilDone:YES;
notice: #selector(dataReady:) (with colon)
Since you're passing an argument to the method, it's presumed data ready is defined something like:
- (void) dataReady:(NSData *)theData ...

Related

Navigation and MapKit makes app crash

I have an application which used top bar navigation and a MapView. On the map view I have placed some annotations and when selecting an annotation, pressing the disclosure button to go into a subview and then going back to the MapView using the back button my application crashes. It does not give me any errors.
Can anyone help me figure out why my application keeps crashing?
I have made a short video showing this mysterious crash (because I'm afraid that I do not explain it very well)
The video can be seen on this link http://snuzzer.dk/pub/iPhoneAppMapKitCrash.mov
Please tell me if you need to see any code in order to determine the reason for the crash. I am not sure what code would be necessary for this as I do not get any error.
EDIT: This is the output of my stack trace:
#0 0x01275a63 in objc_msgSend
#1 0x0586c860 in ??
#2 0x0037ef1d in -[UINavigationController setDisappearingViewController:]
#3 0x0037c4f6 in -[UINavigationController _clearLastOperation]
#4 0x0037ce3f in -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:]
#5 0x00509e23 in -[UINavigationTransitionView _notifyDelegateTransitionDidStopWithContext:]
#6 0x0050afd2 in -[UINavigationTransitionView _cleanupTransition]
#7 0x002f6665 in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]
#8 0x002f64f7 in -[UIViewAnimationState animationDidStop:finished:]
#9 0x01ffa6cb in run_animation_callbacks
#10 0x01ffa589 in CA::timer_callback
#11 0x010f4fe3 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
#12 0x010f6594 in __CFRunLoopDoTimer
#13 0x01052cc9 in __CFRunLoopRun
#14 0x01052240 in CFRunLoopRunSpecific
#15 0x01052161 in CFRunLoopRunInMode
#16 0x01a48268 in GSEventRunModal
#17 0x01a4832d in GSEventRun
#18 0x002d442e in UIApplicationMain
#19 0x00002918 in main at main.m:14
EDIT: It seems that when I do not release my annotationViewController the application does not crash. I will keep playing with the application to see if this is right. Can anyone tell me if this might be right and if so, why? And when would I release it then?
- (void)mapView:(MKMapView *)aMapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
for(MyAnnotation* a in mapView.annotations) { // searching for chosen annotation
if(view.annotation == a) {
// set array from plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"Annotations" ofType:#"plist"];
NSMutableArray* anns = [[NSMutableArray alloc] initWithContentsOfFile:path];
AnnotationDetailViewController *annotationDetailViewController = [[AnnotationDetailViewController alloc] initWithNibName:#"AnnotationDetailViewController" bundle:nil];
annotationDetailViewController.ann = [anns objectAtIndex:[a.annId intValue]];
[self.navigationController pushViewController:annotationDetailViewController animated:YES];
[annotationDetailViewController release]; // this is the one that I think will correct the error
[anns release];
}
}
}
You should look for an ivar in AnnotationDetailViewController that you are under-retaining/over-releasing. I would suspect some UIView, perhaps an IBOutlet that you did not configure to retain, particularly if you also fail to set it to nil in viewDidUnload. I recommend you read Memory Management of Nib Objects if you haven't already.
It's difficult to debug this without the code, or more information about your variables, but that's where I would look given where it's crashing.

iphone app crashes without any console errors or crash logs:

I am newbie here. i am trying to build a quiz app and while my app runs fine for the first iteration of the quiz it exits without any console errors on the second run. PAsting all the code below for reference.
It seems like when i re-run the quiz, -(void) loadNextWord function below does execute but nothing happens after that.
Please help!
Thank you!
Dump from the debugger:
My line 14 in main func is int retVal = UIApplicationMain(argc, argv, nil, nil);
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Program received signal: “EXC_BAD_ACCESS”.
(gdb)
#0 0x025f0907 in objc_msgSend ()
#1 0x05f28da0 in ?? ()
#2 0x023cfc9d in _CFAutoreleasePoolPop ()
#3 0x0001ee67 in -[NSAutoreleasePool release] ()
#4 0x002cfe7f in _UIApplicationHandleEvent ()
#5 0x02d73822 in PurpleEventCallback ()
#6 0x02474ff4 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#7 0x023d5807 in __CFRunLoopDoSource1 ()
#8 0x023d2a93 in __CFRunLoopRun ()
#9 0x023d2350 in CFRunLoopRunSpecific ()
#10 0x023d2271 in CFRunLoopRunInMode ()
#11 0x02d7200c in GSEventRunModal ()
#12 0x02d720d1 in GSEventRun ()
#13 0x002d3af2 in UIApplicationMain ()
#14 0x00002880 in main (argc=1, argv=0xbfffef94) at /Users/vbhardwaj/Documents/ObjectiveC/FinalProject/FunWords/main.m:14
Looking at the stack trace you see the line
[NSAutoreleasePool release]
This tells me that you have released an object too many times i.e. something like :
NSString *string = [NSString stringWithString:#"Hello"]; // This string is autoreleased
[string release]; // This line won't crash but is WRONG!
The above code will not crash immediately but the string will be released and dealloc'd. However, because it's also autoreleased the autorelease pool will try to release it again at some point in the future. You don't know when and will get a random crash.
You've probably done something like that :)
The problem is with multiple-releases.
To be able to properly debug your code, even include files are nessasary.
I can see that you are releasing wordImageView in your code.
You shouldn't do that.
What you should do is to take advantage of properties and do something like
self.wordImageView = nextImageView;
[nextImageView release];
instead of
[wordImageView release]; // release the flagView's memory
wordImageView = nextImageView; // reassign flagView to the new view
You can always use autorelease pools too, but this comes with memory penalty issues.
Btw, although the problem seems to be in the main loop, it isn't there. That is only the location of where the autorelease pool is cleaned, and the problem appears.
In any case, probably have a look at your code and make sure all 'alloc' is handled by a 'release' of the same object inside the same selector.

Why do I have a memory leak in UIApplication

I have an iphone app project. I analysed it using instruments memory leak tool. According to instruments I have 2 leaks the Trace is as follows:
start main UIAplicationMain _run CFRunLoopInMode CFRunLoopRunSpecific PurpleEventCallback _UIAplicationHandleEvent sendEvent: handleEvent:withNewEvent:
After this trace there are two separate traces. What causes this and how can I fix it?
edit:
The leak is on the second line according to instruments
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil); //leak
[pool release];
return retVal;
Are you missing a NSAutoReleasePool for the threads?
That second method looks like some sort of callback being invoked by another component or system thread.
In the implementation, create a NSAutoReleasePool at the top and release it when the method is done:
void MyCallback {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do stuff
[pool release];
}
It might be a false positive. UIApplicationMain probably creates a few objects that are intended to hang around for as long as the application exists and therefore never bothers to release them.

UIAlertView fails to show and results in “EXC_BAD_ACCESS” error

A method is called when a return button on the keyboard is pressed. After calling another method which returns an integer a message is created based on that integer. The message is then passed into an UIAlterView and displayed to the user. The alert doesn't have any options (hence why I'm not calling a delegate), but simply notifies the user of what happened.
Edit: Below is the full method (previously displayed partial). When I comment out everything before the UIAlertView and substitute the string #"test" instead of passing message the Alert is shown successfully. Am I not handling memory correctly with my structure?
- (IBAction)joinButton {
struct userInfo localUser;
[emailAddress resignFirstResponder];
//convert textField text to char array in structure
localUser.firstName = [self convertStringtoCharArray:firstName.text];
localUser.lastName = [self convertStringtoCharArray:lastName.text];
localUser.username = [self convertStringtoCharArray:username.text];
localUser.email = [self convertStringtoCharArray:emailAddress.text];
localUser.ipAddress = [self convertStringtoCharArray:localIPAddress.text];
localUser.latitude = currentLocation.coordinate.latitude;
localUser.longitude = currentLocation.coordinate.longitude;
//pass structure to be sent over socket
int result = [myNetworkConnection registerWithServer:&localUser];
NSString *message = nil;
//process result of sending attempt
if (result == 0) {
//registration succesful
message = [NSString stringWithString:#"Registration successful"];
} else if (result == 1) {
//server unavailable
message = [NSString stringWithString:#"Server unavailable. Please check your wi-fi settings and try again."];
} else if (result == 2) {
//unable to establish connection
message = [NSString stringWithString:#"Unable to communicate with server. Please check your wi-fi settings and try again."];
} else if (result == 3) {
//username already in use
message = [NSString stringWithString:#"Username in use. Try another username."];
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Registration"
message:message
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
}
When I execute the code the iPhone greys out like it is about to display an alert but crashes. I get a EXC_BAD_ACCESS error in the console. Am I not releasing either the alert or the message correctly? Here is the console output:
Program received signal: “EXC_BAD_ACCESS”.
(gdb) backtrace
#0 0x30011944 in objc_msgSend ()
#1 0x3054803e in NSPopAutoreleasePool ()
#2 0x3054c808 in -[NSAutoreleasePool release] ()
#3 0x30936ac4 in _UIApplicationHandleEvent ()
#4 0x3204696c in PurpleEventCallback ()
#5 0x30254a76 in CFRunLoopRunSpecific ()
#6 0x3025416a in CFRunLoopRunInMode ()
#7 0x320452a4 in GSEventRunModal ()
#8 0x308f037c in -[UIApplication _run] ()
#9 0x308eea94 in UIApplicationMain ()
#10 0x000020bc in main (argc=1, argv=0x2ffff508) at /Users/reu2009/Documents/iPhone Development/Development/BuddyTracker/main.m:14
(gdb) frame 10
#10 0x000020bc in main (argc=1, argv=0x2ffff508) at /Users/reu2009/Documents/iPhone Development/Development/BuddyTracker/main.m:14 14 int retVal = UIApplicationMain(argc, argv, nil, nil);
Edit: removed [message release]; and assigned strings using [NSString stringWithString]; based on answers.
i had an issue like this ...i was calling uiAlertView from a background thread ....call it from the main thread
Objects returned from convenience constructors are already set to autorelease. While you declared a pointer to "message", the "message" object itself doesn't belong to you, since you used the #"string" convenience constructor to create the NSString object. Thus, you don't need to release it.
When you release it manually, it then gets released too many times (once manually, and once when the autorelease process rolls around) and throws the error.
Here's some additional information from Apple:
http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html
Good rule of thumb: unless you use one of the alloc or init or copy methods to create an object (or if you retain the object yourself) you don't need to release it, but can rely on the method that actually created it to do that work for you.
Try it with NSZombieEnabled = YES.
Go into the Info of you Executable.
Click on the Arguments tab.
Click + on "Variables to be set in the environment."
Type NSZombieEnable and YES.
When the memory is released that has already been released, NSZombie will display the address, then you can use Instruments to find the actual object. Corbin's Treehouse has a good overview of how to do this:
Instruments on Leopard: How to debug those random crashes in your Cocoa app
Sean is right - you don't need to call [message release] here, because you're never actually retaining the message object.
Instead of just saying message = #"string", you need to say message = [NSString stringWithString:#"string"]; To be completely honest I'm not sure why (maybe someone can comment and I can improve this post!) but that should do the trick.
I had the same problem here with a UIAlertView, in my case, I had another class implementing the alert, and, from another one I was calling a static method. Like the following:
ClassA
...
doSomething {
... some stuff ...
[MyAlertView showAlert];
... some other stuff...
}
What I suspect is that, as the alertview is shown asynchronously when I clicked the button the object was already released.
To verify that, I changed the code to instantiate the alert and not release it. And everythong worked.
My final solution was to declare a variable in the parent view, and deallocate it with the other variables when the view is deallocated.
This could case due to updating UIKit from background thread
I solved it like this
UIAlertView *alertMSG = [[UIAlertView alloc] initWithTitle:nil
message:#"Your mnessage here"
delegate:self
cancelButtonTitle:#"Title here"
otherButtonTitles: nil];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[alertMSG show];
}];

Iphone Core Data crashing on Save

I'm currently writing an Iphone application using Core Data and I get a EXC_BAD_ACCESS error during the [managedObjectContext save:&&error] code line. This crash only happens after I modify certain fields. More specifically my entity has two string fields (out of about 10 fields), that get their values from a the return of a modal view controller (like a text editor). The crash also only happens after these fields are edited, the first time I put a value in it works fine.
The reason I have string with format constructors with just strings is because I was trying to copy construct... not sure if that happens automatically? Thought maybe retain/release messages from those strings (those two are from the modal view controller), were getting released on dismissal of the modal view controller or something. Guess not though because it still doesn't work.
Here's the code section that is crashing:
[EDITED]
- (void)actionSheet:(UIActionSheet *)modalView clickedButtonAtIndex: (NSInteger)buttonIndex
switch(buttonIndex) {
case 0: {
if(message == nil) {
message = [NSEntityDescription insertNewObjectForEntityForName:#"MailMessage" inManagedObjectContext:self.managedObjectContext];
}
message.toString = txtTo.text;
message.fromString = txtFrom.text;
message.subjectString = txtSubject.text;
message.backgroundColor = [NSNumber numberWithInt:[bgColor intValue]];
message.textArray = [NSString stringWithFormat:#"%#", stringTextArray];
message.htmlString = [NSString stringWithFormat:#"%#", stringHTML];
message.timeStamp = [NSDate date];
message.statusCode = [NSNumber numberWithInt:0];
NSError *error = nil;
if (![message.managedObjectContext save:&error]) {
abort();
}
break;
}
case 1: {
break;
}
}
if(buttonIndex != modalView.cancelButtonIndex) {
[webViewBody loadHTMLString:#"<html><head></head><body></body></html>" baseURL:[NSURL URLWithString:#""]];
[self.navigationController popToRootViewControllerAnimated:YES];
}
}
And here's the crash log:
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000015
Crashed Thread: 0
Thread 0 Crashed:
0 libobjc.A.dylib 0x30011940 objc_msgSend + 20
1 CoreData 0x367f7d3e -[NSKnownKeysDictionary1 dealloc] + 82
2 CoreData 0x367f7cda -[NSKnownKeysDictionary1 release] + 34
3 CoreData 0x3687eec4 -[NSManagedObject(_NSInternalMethods) _setOriginalSnapshot__:] + 40
4 CoreData 0x36821030 -[NSManagedObjectContext(_NSInternalAdditions) _clearOriginalSnapshotAndInitializeRec:] + 16
5 CoreData 0x368205f2 -[NSManagedObjectContext(_NSInternalAdditions) _didSaveChanges] + 958
6 CoreData 0x368133bc -[NSManagedObjectContext save:] + 412
7 Decome 0x0001fdd6 -[CreateMessageViewController actionSheet:clickedButtonAtIndex:] (CreateMessageViewController.m:163)
8 UIKit 0x30a6cbd8 -[UIActionSheet(Private) _buttonClicked:] + 256
9 CoreFoundation 0x30256dd4 -[NSObject performSelector:withObject:withObject:] + 20
10 UIKit 0x3096e0d0 -[UIApplication sendAction:to:from:forEvent:] + 128
11 UIKit 0x3096e038 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32
12 UIKit 0x3096e000 -[UIControl sendAction:to:forEvent:] + 44
13 UIKit 0x3096dc58 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 528
14 UIKit 0x309a6e9c -[UIControl touchesEnded:withEvent:] + 452
15 UIKit 0x309a60d4 -[UIWindow _sendTouchesForEvent:] + 520
16 UIKit 0x309a5464 -[UIWindow sendEvent:] + 108
17 UIKit 0x30936e3c -[UIApplication sendEvent:] + 400
Any help is appreciated, Thanks.
UPDATE: Also, even though the program crashes, when I open it back up it the data has saved correctly. So the EXC_BAD_ACCESS must happen after the save has gotten at least far enough to store in the persistent store i think.
If I comment out the save line, the code runs fine now. But it doesn't save after i close and exit. If I run the save line in my Root View Controllers willAppear function, it throws the same EXC_BAD_ACCESS error. The console doesn't say anything other than EXC_BAD_ACCESS
if I do a backtrace I get :
#0 0x30011940 in objc_msgSend ()
#1 0x367f7d44 in -[NSKnownKeysDictionary1 dealloc] ()
#2 0x367f7ce0 in -[NSKnownKeysDictionary1 release] ()
#3 0x3687eeca in -[NSManagedObject(_NSInternalMethods) _setOriginalSnapshot__:] ()
#4 0x36821036 in -[NSManagedObjectContext(_NSInternalAdditions) _clearOriginalSnapshotAndInitializeRec:] ()
#5 0x368205f8 in -[NSManagedObjectContext(_NSInternalAdditions) _didSaveChanges] ()
#6 0x368133c2 in -[NSManagedObjectContext save:] ()
#7 0x0000314e in -[RootViewController viewWillAppear:] (self=0x11b560, _cmd=0x3014ecac, animated=1 '\001') at /Users/inckbmj/Desktop/iphone/Decome/Classes/RootViewController.m:85
Sorry the code wasn't properly formatted before. When this view controller gets created if it is not a new "message" it is passed a message object obtained from a fetchedResultsController like so:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MailMessage *aMessage = (MailMessage *)[fetchedResultsController objectAtIndexPath:indexPath];
[messageView loadMessage:aMessage viewOnly:NO usingTemplate:NO];
messageView.managedObjectContext = self.managedObjectContext;
[self.navigationController pushViewController:messageView animated:YES];
}
(the first set of code is from the MessageViewController.m file which is the class that messsageView is)
It only crashes if I present my EditorViewController as a modal view and then return.
Even if I change the textArray and htmlString lines (which are the only things the modal view affects) to:
message.textArray = #"HELLO";
message.htmlString = #"HELLO";
it still crashes. If I comment both lines out however it doesn't crash.
So it seems like it crashes if I present a modal view and then try to edit either the textArray or htmlString fields of my NSOManagedObject...
Here is where i present the view:
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event {
if(!viewOnly) {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: txtTo];
location = [touch locationInView: webViewBody];
if(CGRectContainsPoint(webViewBody.bounds, location)) {
[editor loadTextArrayString:stringTextArray];
[self presentModalViewController:editor animated:YES];
}
}
}
and where i dismiss it:
-(void)returnWithTextArray:(NSString *)arrayString HTML:(NSString *)html bgColor:(NSNumber *)numColor {
[self dismissModalViewControllerAnimated:YES];
self.stringTextArray = [NSString stringWithFormat:#"%#", arrayString];
self.stringHTML = [NSString stringWithFormat:#"%#", html];
self.bgColor = [NSNumber numberWithInt:[numColor intValue]];
[webViewBody loadHTMLString:self.stringHTML baseURL:[NSURL URLWithString:#""]];
}
You are only guaranteed to retain access to a managed object from the context as long as a change is pending to that object (insert, update, delete). As soon as you make a call to save:, you can lose your reference to the managed object.
While you stopped getting the error when you set setRetainsRegisteredObjects:YES, you may have introduced a memory management issue, as you are setting the managed object's lifetime to be dependent on the lifetime of the managed object context. If you're passing your context around throughout your app, this could get rather large if you have a large object hierarchy.
You can read more in the Apple docs here: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/MO_Lifecycle.html
Solved the problem though I'm not sure I'm addressing the actual root cause. The error was eliminated when I added this line:
[managedObjectContext setRetainsRegisteredObjects:YES];
To where I create the managedObjectContext. So I guess it had to do with retain counts. I'm guessing that maybe instance variables get released partially or temporarily or something when modal views are presented? I don't know. In any case, this error was eliminated the the program works fine now.
Just to help others having the same issue, and reinforcing Steff's response above, the likely cause of this error is that you are trying to release a NSManagedObject.
I have seen many funny behaviours with CoreData on iPhone that were solved by resetting content and settings in the iPhone simulator.
I know this is an oldie but I had the same issue so thought I'd add my tuppence as to how I solved the issue, mine was caused by manually releasing the managed object within the modal view, I removed the release calls and everything is working fine :) according to the docs you shouldn't manually try and release managed objects anyway as the context will look after all of that. That's my experience anyway, search through your code for over-released values.
You must set the FRC cache to nil
I have solved a similar problem by making sure that the object is fetched, so for the example above:
if ( message == nil ) {
message = [NSEntityDescription insertNewObjectForEntityForName:#"MailMessage" inManagedObjectContext:self.managedObjectContext];
} else {
NSError *error = nil;
message = (MailMessage *)[managedObjectContext existingObjectWithID:[message objectID] error:&error];
}