views:

238

answers:

2

I have a modal view controller that creates core data changes in it's own context, and when I click done, it saves the changes (that dispatches the merge changes notification), notifies the delegate and dismisses.

My problem is that I need the delegate to receive the message after my main context has merged with the changes of the editing context. I want the delegate call to take place on the next run loop but I'm having problems with object lifetimes. I've thought of the following:

  1. Make call to [delegate performSelector:withObject:afterDelay:] however it seems that that message is not recognised. My delegate conforms to the NSObject protocol but that doesn't include the perform selector with delay.
  2. Create a method in my view controller: informDelegateWithObject: that calls the delegate method, and call that method after a delay. I.e. [self performSelector:@selector(informDelegateWithObject:) withObject:.. afterDelay:..]. This could work, however, as my view controller is being dismissed, if the delay is several seconds then it would have been released from memory and wouldn't that cause a crash when it comes to invoking?
  3. Create an instance of NSInvocation. I have thought about this, however, what is the lifetime of this object? If I create it using [NSInvocation invocationWithMethodSignature:] then wouldn't the NSInvocation object be autoreleased, and not be around for the next run loop? Let alone several seconds. And as my modal view controller is being dismissed and released, I can't store the invocation object in my view controller.

Any suggestions?

+1  A: 

You should merge contexts into the delegate.

Say that you press Save into you modal controller: you will send a myViewController:didFinishSaving: to the delegate.

This delegate into myViewController:didFinishSaving: implementation will save, merge and dismiss the modal view controller.

I hope I have understood your problem. Bye! :)

muccy
Thanks for your response. I've actually got a different pattern going, it's a fairly complex app and my EVC (edit view controller) is called from multiple places and hence can have several delegates. The context and the saving is all neatly handled from the EVC. I'm really just wanting to know the best way to invoke methods after a delay with the object life time issues described in the question. Any ideas?
Michael Waterfall
You can still use my pattern.In myViewController:didFinishSaving: implementation you can call a method on myViewController...like [myViewController saveAndMergeWithMOC:self.managedObjectContext], then dismiss.Speaking about invoking selectors with delay...I'm seeing nothing wrong using performSelector:withObject:afterDelay:. If you want suppress compiler's warning you can define a protocol that includes that method.In any case it has to work, because UIViewController inherits from NSObject, and @selector(performSelector:withObject:afterDelay:) will be found by the Objective-C runtime
muccy
+1  A: 

You might look at Apple's Core Data Books tutorial which works along the lines that muccy describes. Saving happens after the modal view is dismissed and control is returned to the parent view controller. The parent contains the update code and fires notifications required to merge changes (whether that happens in the delegate or elsewhere).

Alex Reynolds
Thanks for your response, and your help with other questions of mine on here :-) As mentioned in my comment to muccy's answer, I'm using a slightly different pattern, it's a fairly complex app and my edit view controller neatly handles the edit context and the saving. I'm really just wanting to know the best way to invoke methods after a delay with the object life time issues described in the question. Any ideas?
Michael Waterfall