my app crashed when nsstring getting contents of URL.
website = [NSString stringWithFormat:#"hidden."];
contents = [NSString stringWithContentsOfURL:[NSURL URLWithString:website] encoding:NSUTF8StringEncoding error:nil];
the crash log is:
void _WebThreadLockFromAnyThread(bool), 0x865cc40: Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread.
2012-07-10 11:15:17.654 MyApplication[1505:19407] OK // some output
2012-07-10 11:15:17.660 MyApplication[1505:19407] bool _WebTryThreadLock(bool), 0x865cc40: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
1 WebThreadLock
2 -[UITextRangeImpl isEmpty]
3 -[UITextRange(UITextSelectionAdditions) _isCaret]
4 -[UITextSelectionView setCaretBlinks:]
5 -[UIKeyboardImpl setCaretBlinks:]
6 -[UIKeyboardImpl setDelegate:force:]
7 -[UIKeyboardImpl setDelegate:]
8 -[UIPeripheralHost(UIKitInternal) _reloadInputViewsForResponder:]
9 -[UIResponder(UIResponderInputViewAdditions) reloadInputViews]
10 -[UIResponder(Internal) _windowBecameKey]
11 -[UITextField _windowBecameKey]
12 -[UIWindow makeKeyWindow]
13 -[UIWindow makeKeyAndVisible]
14 -[MyApplicationAppDelegate checkLogin]
15 -[NSThread main]
16 __NSThread__main__
17 _pthread_start
18 thread_start
the code is called with [self performSelectorInBackground:#selector(checkLogin) withObject:nil]; from IBAction. what i am doing wrong?
(Xcode 4.3, Mac OS X Lion, iPhone Simulator 5.1)
According to that error message, you're trying to update a UIKit object from a background thread, and the UI can only be updated from the main thread.
Instead, use self performSelectorOnMainThread to call back to the main thread to update your UI with whatever information you received when your web call returns.
From your main thread:
[self performSelectorInBackground:#selector(checkLogin) withObject:nil];
In the background:
- (void)checkLogin {
// Do web stuff
...
[self performSelectorOnMainThread:#selector(updateUI)
withObject:nil
waitUntilDone:NO];
}
- (void)updateUI {
[statusLabel setText:#"Done!"];
}
Try using
- (id)performSelector:(SEL)aSelector withObject:(id)anObject.
Related
I am developing an app that captures images from iDevice's camera and upload it to web service.
NO problem everything is working fine except the device's camera. Device's camera is driving my crazy. I am using below code to allow user to capture images. Sometimes camera shows preview and sometimes doesn't. Instead of preview is just shows complete darkness on screen. If I switch from rear to front camera is starts working fine. I have even trying deleting all background apps from device and clearing as much memory as I could; still no luck and I am stuck. :(
- (IBAction)addNewImage:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
// Take picture from camera
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
// set no to take as much pictures as user want.
imagePicker.showsCameraControls = YES;
// Show user the camera
[self presentModalViewController:imagePicker
animated:YES];
}
else
{
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:imagePicker
animated:YES];
}
}
I have a customer who had this issue. They must have selected to not allow access to the camera. We had to change the camera privacy setting for the app in Settings. When we switched that back on, no more black camera screen.
I was facing the same issue in iOS7 for around a month, After a long long head breaking code review of the entire app, i was able to identify the problem.
I was enumerating an
IBOutletCollection(UILabel) NSArray *staticLabelsCollection;
array Concurrently updating the labels texts, which got executed simultaneously on multiple threads.
[self.labelsArr enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UILabel * label = (UILabel*)obj;
label.text=[NSString stringWithFormat:#"%d",idx+2];
}];
This created the problem of updating the UIKit elements on other than main thread.
I was able to catch the this issue by enabling the environment variable CA_DEBUG_TRANSACTIONS=1 in Xcode which generated warnings in device console
Nov 20 18:40:26 iPad2 CameraTest[1757] <Warning>: CoreAnimation: warning, deleted thread with uncommitted CATransaction; created by:
0 QuartzCore 0x32a553b3 <redacted> + 266
1 QuartzCore 0x32a55269 <redacted> + 224
2 QuartzCore 0x32a56871 <redacted> + 24
3 QuartzCore 0x32a56eed <redacted> + 40
4 QuartzCore 0x32a619ed <redacted> + 412
5 QuartzCore 0x32a6184b <redacted> + 46
6 QuartzCore 0x32a61819 <redacted> + 44
7 UIKit 0x32ddfe53 <redacted> + 86
8 CameraTest 0x000923b5 __35-[ViewController blockEnumeration:]_block_invoke + 184
9 CoreFoundation 0x305aa821 <redacted> + 92
10 libdispatch.dylib 0x3b3308eb <redacted> + 134
11 libdispatch.dylib 0x3b32fd71 <redacted> + 220
12 libdispatch.dylib 0x3b32ff59 <redacted> + 56
13 libsystem_pthread.dylib 0x3b46adbf _pthread_wqthread + 298
14 libsystem_pthread.dylib 0x3b46ac84 start_wqthread + 8
Fixing these 'uncommited CATransactions' by forcing them to run on the main thread fixed the black camera issues.
I was able to fix it by removing Option: NSEnumerationConcurrent from enumeration.
The sample app which could constantly reproduce the problem can be downloaded here
Hope the sample app could give some insight and the work around for the issue.
I had faced this issue in my app. Though I never found out the what the issue was, I rewrote my code to define a property of UIIMagePickerController type and initialize it once in the getter. Used this property to initialize the camera view :
getter:
-(UIImagePickerController *) imagePicker{
if(!_imagePicker){
_imagePicker = [[UIImagePickerController alloc] init];
_imagePicker.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
_imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
else{
_imagePicker.sourceType =UIImagePickerControllerSourceTypePhotoLibrary;
}
}
return _imagePicker;
}
- (IBAction)addNewImage:(id)sender{
if (self.imagePicker)
{
[self presentViewController:self.imagePicker animated:YES completion:^{}];
}
}
For some reason this got rid of the issue with preview sometimes showing a black screen
In ios7, you should set mainWindow.rootViewController = a class has kind is UIViewController. It's work for me.
If rootViewController is other, ex: UITabbarController, UINavigationController..., the black screen of camera will appear.
I have a UIViewController. In this controller I programmatically create a UITextView and set its delegate as my controller. I do this because I dont want to start editing the textView when I tap it.
ViewDidLoad method
UITextView* textView = [[UITextView alloc] initWithFrame:CGRectMake(9, 10, 302, 200)];
[textView setDelegate:self];
[self.view addSubview:textView];
[textView release];
I implemented the textViewShouldBeginEditing method to return NO here to disable the keyboard from showing up.
textViewShouldBeginEditing method
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
NSLog(#"Shouldbegin");
return NO;
}
The problem that appears
When I tap the textView it works once, but if i tap it again it will crash the application without any log. The weird thing when I hold the textView and release it, it will work like I want it to work. A normal single tap on the other hand doesn't work a second time.
Edit
Single tapping quickly after each other also seems to work, so it seems that it wont work after i wait x seconds.
After some testing I found out it seems to be an iOS 5.X > bug. When running my App in a 4.3 device/simulator it works like it should. The error log on a iOS 5.1 device says the following:
Date/Time: 2012-04-17 14:00:49.497 +0200
OS Version: iPhone OS 5.1 (9B176)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000014
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 TextInput 0x36bf69e8 TI::Favonius::BeamSearch::choose_hit_test_node(WTF::RefPtr<TI::Favonius::SearchNode> const&, WTF::RefPtr<TI::Favonius::KeyAreaNode> const&, WTF::RefPtr<TI::Favonius::SearchNode> const&, WTF::RefPtr<TI::Favonius::SearchNode> const&) + 12
1 TextInput 0x36bf6d1e TI::Favonius::BeamSearch::update_for_touch(unsigned int, WTF::PassRefPtr<TI::Favonius::KeyAreaNode>) + 602
2 TextInput 0x36bfb5c2 TI::Favonius::StrokeBuildManager::update_search_for_touch(unsigned int, int) + 66
3 TextInput 0x36bfb97c TI::Favonius::StrokeBuildManager::key_down_or_drag_hit_test_for_UI(bool, CGPoint, double, int, int, float, bool, ZT::LayoutDictionaryContext&, bool, int) + 216
4 TextInput 0x36bddf54 TIInputManagerZephyr::simulate_touches_for_input_string() + 344
5 TextInput 0x36bed8ba -[TIKeyboardInputManagerZephyr candidates] + 214
6 UIKit 0x31066616 -[UIKeyboardImpl generateAutocorrectionReplacements:] + 82
7 UIKit 0x31108a96 __71-[UITextInteractionAssistant scheduleReplacementsForRange:withOptions:]_block_invoke_0 + 370
8 UIKit 0x3110ec62 -[UITextSelectionView calculateAndShowReplacements:] + 6
9 Foundation 0x3762192c __NSFireDelayedPerform + 408
10 CoreFoundation 0x361a1a2c __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 8
11 CoreFoundation 0x361a1692 __CFRunLoopDoTimer + 358
12 CoreFoundation 0x361a0268 __CFRunLoopRun + 1200
13 CoreFoundation 0x3612349e CFRunLoopRunSpecific + 294
14 CoreFoundation 0x36123366 CFRunLoopRunInMode + 98
15 GraphicsServices 0x324e3432 GSEventRunModal + 130
16 UIKit 0x30e70e76 UIApplicationMain + 1074
I did find a solution. I don't really like working around Apple bugs but sometimes you have to. It is three steps...
1) replace the default keyboard with an invisible view
- (void)viewDidLoad
{
[super viewDidLoad];
myTextView.inputView = customKeyboard;
}
2) answer YES to allow editing
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
return YES;
}
3) In textViewDidChangeSelection resign the first responder to hide the cursor
- (void)textViewDidChangeSelection:(UITextView *)textView{
[textView resignFirstResponder];
}
If you don't want to start editing of UITextView when you tapped it:
UITextView* textView = ...;
textView.editable = NO;
After some testing I found out it seems to be an iOS 5.X > bug. When running my App in a 4.3 device/simulator it works like it should.
Look in my main post where i edited the logfile.
-(BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
[txtView resignFirstResponder];
}
and release txtView in dealloc method
Swift 4.2
The best and easy way to solve this just make undo manager as false
textView.undoManager?.disableUndoRegistration()
This error appears if you have change the view at run time like within the table, and cell will be reloaded on tapping,
Im getting the following exception when attempting to merge a managed context (running on a background thread) with my main managed context (on mainthread). I cant seem to catch the exception in my own #try expression. Does anyone have any insight into this issue?
I'm using the default merge policy but im not sure this is correct - this issue is very intermittent - happens rarely but is causing my app to crash.
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread: 0
Last Exception Backtrace:
0 CoreFoundation 0x37e3b8bf __exceptionPreprocess + 163
1 libobjc.A.dylib 0x319211e5 objc_exception_throw + 33
2 CoreData 0x344b7ea5 -[NSSQLiteStatement cachedSQLiteStatement] + 1
3 CoreData 0x344b774f -[NSSQLiteConnection prepareSQLStatement:] + 55
4 CoreData 0x3455b049 -[NSSQLChannel selectRowsWithCachedStatement:] + 61
5 CoreData 0x34586d63 newFetchedRowsForFetchPlan_MT + 783
6 CoreData 0x344bfb07 -[NSSQLCore newRowsForFetchPlan:] + 351
7 CoreData 0x34565011 -[NSSQLCore fetchRowForObjectID:] + 1005
8 CoreData 0x344d1a57 -[NSSQLCore newValuesForObjectWithID:withContext:error:] + 195
9 CoreData 0x344d0f83 _PFFaultHandlerLookupRow + 423
10 CoreData 0x3450e111 -[NSFaultHandler fulfillFault:withContext:] + 25
11 CoreData 0x34518999 -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:] + 77
12 CoreData 0x345178ef -[NSManagedObject(_NSInternalMethods) _newAllPropertiesWithRelationshipFaultsIntact__] + 79
13 CoreData 0x345284db -[NSManagedObjectContext(_NSInternalChangeProcessing) _establishEventSnapshotsForObject:] + 47
14 CoreData 0x3452694b -[NSManagedObjectContext deleteObject:] + 155
15 CoreData 0x345238a1 -[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] + 813
16 CoreData 0x34522c35 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 189
17 myapp 0x0008f0e9 0x8d000 + 8425
18 CoreFoundation 0x37d9a22b -[NSObject performSelector:withObject:] + 43
19 Foundation 0x31d75757 __NSThreadPerformPerform + 351
20 CoreFoundation 0x37e0fb03 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
21 CoreFoundation 0x37e0f2cf __CFRunLoopDoSources0 + 215
22 CoreFoundation 0x37e0e075 __CFRunLoopRun + 653
23 CoreFoundation 0x37d914dd CFRunLoopRunSpecific + 301
24 CoreFoundation 0x37d913a5 CFRunLoopRunInMode + 105
25 GraphicsServices 0x3790ffcd GSEventRunModal + 157
26 UIKit 0x35221743 UIApplicationMain + 1091
I init the background context in start() of a nsoperation like so:
AppDelegate *appController = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[appController setPersistentStore:_managedObjectContext];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedDeletedObjects:) name:NSManagedObjectContextDidSaveNotification object:_managedObjectContext];
I also set up a notification event which is called when objects are deleted on the background managed context, the callback then does:
-(void)receivedDeletedObjects:(NSNotification *)note
{
AppDelegate *appController = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *mainContext = [self managedObjectContext];
[mainContext performSelectorOnMainThread:#selector(mergeChangesFromContextDidSaveNotification:) withObject:note waitUntilDone:NO];
}
Thats pretty much the code. I have 4 different background threads each with its own managed context doing the same thing merging with the main context in this manner. Im wondering multiple threads are getting into mergeChangesFromContextDidSaveNotification at the same time but this shouldnt be the case as it is always called on the mainthread.
How about this:
(all in AppDelegate, call freshContextForBackgroundTask from a background Thread and use save: to trigger the merge.) Note syncObj is a plain NSObject instance needed for synchronization within the app delegate when using many background threads (or just have bad luck with scheduling)
-(NSManagedObjectContext*) freshContextForBackgroundTask {
#synchronized(syncObj) {
NSManagedObjectContext* r = [[NSManagedObjectContext alloc] init];
[r setPersistentStoreCoordinator:self.managedObjectContext.persistentStoreCoordinator];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(backgroundContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:r];
return r;
}
}
- (void)backgroundContextDidSave:(NSNotification *)notification {
/* Make sure we're on the main thread when updating the main context */
//NSLog(#"merging change: %#",notification);
dispatch_async(dispatch_get_main_queue(), ^{
NSManagedObjectContext *context = [self managedObjectContext];
// this for loop may not be needed for your purpose.
for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) {
[[context objectWithID:[object objectID]] willAccessValueForKey:nil];
}
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
});
}
Your approach seems strange. Especially when you set your app delegate's persistent store to the (nil) one of the freshly init'ed context.
I got the following crash report from iTunesconnect. Is the UIActivityIndicatorView bugged?
Date/Time: 2009-09-26 12:33:02.034 +1000
OS Version: iPhone OS 3.0 (7A341)
Report Version: 104
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread: 0
Thread 0 Crashed:
0 libSystem.B.dylib 0x31d54964 lstat + 8
1 Foundation 0x3055baf6 _NSFileExistsAtPath
2 Foundation 0x3055f6a2 -[NSFileManager fileExistsAtPath:]
3 WinterBoard.dylib 0x0019f034 0x19c000 + 12340
4 WinterBoard.dylib 0x001a032c 0x19c000 + 17196
5 UIKit 0x30972650 +[UIActivityIndicatorView _loadResourcesForStyle:]
6 UIKit 0x30972498 -[UIActivityIndicatorView setActivityIndicatorViewStyle:]
7 UIKit 0x309723bc -[UIActivityIndicatorView initWithFrame:]
8 UIKit 0x30a113f8 -[UIActivityIndicatorView initWithActivityIndicatorStyle:]
Below is how I created it:
UIActivityIndicatorView *act = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
act.center = CGPointMake(160, 190);
[act startAnimating];
[self addSubview:act];
[act release];
As you can see in the log, it goes wrong with -[NSFileManager fileExistsAtPath:]. Below that line in the stack trace, you see that it was being called by Winterboard.dylib.
Winterboard is an application for jailbroken iPhones to modify the appearance of the OS which is not supported by Apple. In this case, Winterboard is to blame for the crash of your application, not UIKit.
You can't do anything about that, it's probably a bug in Winterboard which only users with a jailbroken iPhone and Winterboard may have.
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];
}