• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Core Data: Progress bar using Sheet, modifying context in thread
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Core Data: Progress bar using Sheet, modifying context in thread


  • Subject: Re: Core Data: Progress bar using Sheet, modifying context in thread
  • From: Jakob Olesen <email@hidden>
  • Date: Fri, 4 Aug 2006 11:45:10 +0200


On 04/08/2006, at 6.05, Bill Coleman wrote:

Question 1: I'd like the import or export process to be document- modal, with the progress of the operation displayed in a sheet. This is a little tricky, since once you call beginSheet: modalForWindow: ..., you can't do any more processing. So, to perform the actual operation, I first start an NSThread. Getting it to quit properly was tricky, as you have to use performSelectorOnMainThread: to get the endSheet: call to work.


My question is -- is this the right way to do this? Is there a better way? It seems to be fraught with problems.

You should try to avoid using a thread for something like this. Most classes in AppKit are not thread safe, so you should only touch them in the main thread. This goes for NSManagedObjectContext and NSManagedObject as well.


Read the Core Data documentation on multithreading, but really, try to avoid threads.

Question 2: Export seems to work ok. Import, however, acts a bit funny. I create new rows for import by calling [NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:]. I add the object to the NSArrayController by calling addObject:. The addObject: message, however, doesn't seem to be necessary for reasons I don't fully understand.

When you set "Automatically prepares content", the controller observer notifications from the NSManagedObjectContext.


What I'm seeing is that the objects end up showing up in the NSTableView as each one is imported. This didn't happen before I added the sheet and thread. It appears that the table is observing the insertions and trying to update -- which really slows down the import process.

My question is -- is there any way I can turn off this update of the NSTableView until I'm done? Can I create instances of managed objects and then add them to the managed context all at once?

No, but you can probably turn off "Automatically prepares content" during the import. (I haven't tried that)


This smells funny. DO NOT use the NSManagedObjectContext bound to your controllers outside the main thread.

Question 3: During a long import, the update of the NSTableView often stops after a number of rows are inserted. (It appears to always be powers of 2 -1, eg 63, 255) Sometimes, I get bad access exceptions during this update process. This makes me thing I'm doing something wrong in this multi-threaded environment.

The exceptions are probably race conditions.

My progress bar also seems to jump back and forth a bit, even though I'm steadily increasing the value passed to setDoubleValue:, and I don't change the maximum value after the import starts.

I believe NSProgressIndicator isn't thread safe either. Somebody correct me if I am wrong.


You should try to do the import in the main thread. The sheet does not prevent that. You want to surrender the CPU to the run loop at regular intervals in order to update the screen, respond to "Cancel" buttons, and generally avoid the spinning beach ball. You can get the run loop to call you back using [self performSelector:afterDelay:] or NSNotificationQueue. This is cooperative multitasking.

If you really must use a thread, here is how to do it:

Create a new NSManagedObjectContext, hook it up to your NSPersistentStoreCoordinator, and use only the new context from the thread.
Always use -[performSelectorOnMainThread:] to send messages back, even for the NSProgressIndicator.
When you are done, save the context and get rid of it. Watch out for retain cycles caused by relationships.
Back in the main thread, tell your controller to fetch the new rows.


This method works well if you are only inserting new objects. If you are updating existing objects, you need to refresh those in the main context. If you are deleting objects, things get funky. If you are using transient properties the way it is described in the docs and examples, you're in trouble.

By the way, your export being "OK" is just luck. If you are not creating a new NSManagedObjectContext for your thread, it too will break some day.


_______________________________________________ Do not post admin requests to the list. They will be ignored. Cocoa-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
  • Follow-Ups:
    • Re: Core Data: Progress bar using Sheet, modifying context in thread
      • From: Chris Suter <email@hidden>
    • Re: Core Data: Progress bar using Sheet, modifying context in thread
      • From: Bill Coleman <email@hidden>
References: 
 >Core Data: Progress bar using Sheet, modifying context in thread (From: Bill Coleman <email@hidden>)

  • Prev by Date: Re: Core Data: Progress bar using Sheet, modifying context in thread
  • Next by Date: Re: resolving aliases
  • Previous by thread: Re: Core Data: Progress bar using Sheet, modifying context in thread
  • Next by thread: Re: Core Data: Progress bar using Sheet, modifying context in thread
  • Index(es):
    • Date
    • Thread