Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does anyone know whats going on here ? Core Data / iCloud

So whats happening here is the app has just received the NSPersistentStoreDidImportUbiquitousContentChangesNotification, and I have just called

- (void)storesDidUpdate:(NSNotification*)note {
    FLOG(@"storesDidUpdate ");
    [_managedObjectContext mergeChangesFromContextDidSaveNotification:note];

    // Refresh user Interface
    [[NSNotificationCenter defaultCenter] postNotificationName:@"iProjectCoreDataUpdated"
                                                        object:self];

    [self updateDetails];
}

And now the app is trying to update a UITextView with a fresh copy of text by simply doing the following:

self.detailText.attributedText  = [self.detailItem valueForKey:@"scope"];

Where detailItem is a NSManagedObject retrieved prior to receiving the update from iCloud.

Not sure why the textContainer is complaining or what its complaining about, and also not sure why importing logs is happening because I have already received a notification that its done!

Strangely other UITableViews update correctly if I just call reloadData.

Any ideas on whether I am doing something wrong here? Note that if I don't try and update the textView it works fine and if I close the view and go back to it then I get the correct data.

Also when I restart the app all the data is there, no corruptions or anything, in fact the app seems remarkably robust in most respects when it comes to the Core Data store, despite things blowing up on either side of iCloud!

Oh and the reloadFetchedResults is a bit misleading because I don't seem to need to do that, so the method name is a hangover from the past, all I am doing is refreshing values in the UI in this call.

2013-10-09 07:25:53.783 MyApp[4509:510b] OpeningViewController.reloadFetchedResults: called 2013-10-09 07:25:53.786 MyApp[4509:510b] InfoDetailViewController.reloadFetchedResults: called in InfoDetailViewController 2013-10-09 07:25:53.788 MyApp[4509:510b] * Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView *, NSTextContainer *, NSUInteger)(), /SourceCache/UIFoundation/UIFoundation-258/UIFoundation/TextSystem/NSLayoutManager_Private.m:1510 2013-10-09 07:25:53.793 MyApp[4509:510b] -_PFUbiquityRecordImportOperation main: CoreData: Ubiquity: Error importing transaction log: transactionLogLocation: : /var/mobile/Library/Mobile Documents/HHHHHHNNNN~com~mycompany~MyApp/CoreData/New Document/duncangroenewald~simAABC628E-9D5E-58F7-9B8D-0BC724C6D0C8/New Document/W8MckEJ0x2d~HZZIeUH2be6hs41TEOONzKIrCuLcuP4=/6C953E7C-B2AF-47F7-B828-DD062B96415D.1.cdt transactionNumber: 5 , exception: Only run on the main thread! User Info: (null) 2013-10-09 07:25:53.803 MyApp[4509:510b] -_PFUbiquityRecordsImporter operation:failedWithError:: CoreData: Ubiquity: Import operation encountered an error: Error Domain=NSCocoaErrorDomain Code=134060 "The operation couldn’t be completed. (Cocoa error 134060.)" UserInfo=0x16d882c0 {exception=Only run on the main thread!} userInfo: { exception = "Only run on the main thread!"; }. While trying to import the log file at the URL: transactionLogLocation: : /var/mobile/Library/Mobile Documents/HHHHHHNNNN~com~mycompany~MyApp/CoreData/New Document/duncangroenewald~simAABC628E-9D5E-58F7-9B8D-0BC724C6D0C8/New Document/W8MckEJ0x2d~HZZIeUH2be6hs41TEOONzKIrCuLcuP4=/6C953E7C-B2AF-47F7-B828-DD062B96415D.1.cdt transactionNumber: 5 2013-10-09 07:25:53.809 MyApp[4509:510b] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!' *** First throw call stack: (0x2ff23f53 0x3a6996af 0x2ff23e2d 0x308cb1df 0x3796643d 0x37966185 0x3798f7bb 0x379926f7 0x37992759 0x379b378b 0x379b331f 0x379b2f0d 0x3273b05d 0x129717 0x2fee6121 0x2fe5a317 0x3083edcd 0x308436ab 0x118263 0x2fee6121 0x2fe5a317 0x2fd8c69f 0x2fd8cc93 0x2fd813dd 0x3085197b 0x308f5b35 0x3ab83297 0x3ab8309b 0x3ab83d15 0x3ab83f8d 0x3acbedbf 0x3acbec84) libc++abi.dylib: terminating with uncaught exception of type NSException

EDIT: I have posted some sample Core Data/iCloud apps for iOS and OSX here - they include background threads for loading/deleting data as well as iCloud sync. Hopefully address the issue described here. http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/

like image 806
Duncan Groenewald Avatar asked Oct 08 '13 20:10

Duncan Groenewald


2 Answers

OK here is what seems to fix it - I guess I never realised that receiving a notification would run on another thread. Is that normal behaviour, are all Core Data notifications you receive called on a background thread ? If so do you always have to make sure anything you do is then running on the correct thread ?

- (void)storesDidUpdate:(NSNotification*)note {
    FLOG(@"storesDidUpdate ");
    [_managedObjectContext mergeChangesFromContextDidSaveNotification:note];

    [[NSOperationQueue mainQueue] addOperationWithBlock:^ {
        //Your code goes in here
        LOG(@" Main Thread Code");

        // Refresh user Interface
        [[NSNotificationCenter defaultCenter] postNotificationName:@"CoreDataUpdatedNotification"
                                                        object:self];
    }];

}

EDIT:

I have finally gotten around to documenting how I got Core Data and iCloud to work pretty reliably, including handling moving to and from iCloud in response to the use changing their Use iCloud preference settings. I was unable to find a good explanation with working code when I was trying to figure out how to get it working so I hope this proves useful to others. Included is a video of the app working so you can see how it behaves to help you figure out if it's what you are wanting to achieve.

http://ossh.com.au/design-and-technology/software-development/

like image 163
Duncan Groenewald Avatar answered Oct 12 '22 03:10

Duncan Groenewald


I got the same problem. It was exactly the issue @John Rogers explained. I created UITextViews and in the background I called a URL to get some data which should be inserted into my generated UITextViews. But the Problem was the method sendAsynchronousRequest which will be called in background and cause the crash in my case.

I could solve the problem by performing the specific selector on main thread when receiving my data. So maybe you can insert you're method call into another method and call it this way:

[self performSelectorOnMainThread:@selector(received:) 
                       withObject:data 
                    waitUntilDone:YES];

This way you get back to the main thread again.

like image 22
Alex Cio Avatar answered Oct 12 '22 05:10

Alex Cio