0

I'm using Stanford's CoreDataTableViewController to display a dynamic table.

How the app works: To add a row to this table, a child screen is popped for data entry, and when the child screen closes, the newly created managedObject is inserted, and a callback reloads the table.

I've noticed that newly added rows are intermittently missing from the table upon re-entering the screen. I noticed this behaviour only occurs when the UIManagedDocument object is created for the first time using saveToURL. Subsequently, after restarting the app and opening the UIManagedDocument using openWithCompletionHandler, the list always displays correctly.

Here's the code I'm using to create/open the UIManagedDocument:

- (void)performWithDocument:(OnDocumentReady)onDocumentReady
{
    void (^OnDocumentDidLoad)(BOOL) = ^(BOOL success)
    {
        NSLog(@"Called OnDocumentDidLoad");
        onDocumentReady(self.document);
    };

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]])
    {
        [self.document saveToURL:self.document.fileURL
                forSaveOperation:UIDocumentSaveForCreating
               completionHandler:OnDocumentDidLoad];
    }
    else if (self.document.documentState == UIDocumentStateClosed)
    {
        NSLog(@"Calling openWithCompletionHandler:OnDocumentDidLoad");
        [self.document openWithCompletionHandler:OnDocumentDidLoad];
    }
    else if (self.document.documentState == UIDocumentStateNormal)
    {
        OnDocumentDidLoad(YES);
    }
}

When running the above code, onDocumentDidLoad() is always called, and the success flag is YES.

Any help would be most appreciated. Thanks in advance!

-- Edited the following code to show my method of creating, then closing and reopening the document in response to Jody - I still encountered the same issue. ---

- (void)performWithDocument:(OnDocumentReady)onDocumentReady
{
    void (^OnDocumentDidLoad)(BOOL) = ^(BOOL success)
    {
        NSLog(@"Called OnDocumentDidLoad success: %d", success);
        onDocumentReady(self.document);
    };

    void (^OnDocumentDidClose)(BOOL) = ^(BOOL success)
    {
        NSLog(@"Called OnDocumentDidClose, openWithCompletionHandler success: %d", success);
        [self.document openWithCompletionHandler:OnDocumentDidLoad];
    };

    void (^OnDocumentDidSave)(BOOL) = ^(BOOL success)
    {
        NSLog(@"Called OnDocumentDidSave success: %d", success);
        if (self.document.documentState == UIDocumentStateClosed)
        {
            NSLog(@"Calling openWithCompletionHandler:OnDocumentDidLoad from onDocumentDidSave - was closed");
            [self.document openWithCompletionHandler:OnDocumentDidLoad];
        }
        else if (self.document.documentState == UIDocumentStateNormal)
        {
            // TODO Close and reopen?
            NSLog(@"Calling closeWithCompletionHandler:OnDocumentDidClose from onDocumentDidSave - was normal");

            [self.document closeWithCompletionHandler:OnDocumentDidClose];
        }
    };

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]])
    {
        // Database doesn't exist, create it, then close and reopen in completion handler
        [self.document saveToURL:self.document.fileURL
                forSaveOperation:UIDocumentSaveForCreating
               completionHandler:OnDocumentDidSave];
    }
    else if (self.document.documentState == UIDocumentStateClosed)
    {
        // Open existing database
        NSLog(@"Calling openWithCompletionHandler:OnDocumentDidLoad");
        [self.document openWithCompletionHandler:OnDocumentDidLoad];
    }
    else if (self.document.documentState == UIDocumentStateNormal)
    {
        // Already opened
        OnDocumentDidLoad(YES);
    }
}
Jody Hagins
  • 27,943
  • 6
  • 58
  • 87
iht
  • 692
  • 1
  • 8
  • 15

1 Answers1

0

You did not indicate which version of iOS you are using, which is almost always important.

There was an iOS 5 issue when creating a document. I resorted to the following a long time ago when creating a UIManagedDocument. It's still in my library code as I was never motivated enough to take the time to see if the issues were ever fixed.

If the document does not exist, save it for creating, and in the completion handler, close it, and in that completion handler, open it. That way, I never really used a document unless it already existed.

Jody Hagins
  • 27,943
  • 6
  • 58
  • 87
  • Thanks for your response. I'm on iOS 6. Yeah, I also tried closing it in the completion handler and re-opening it, but it didn't make a difference - the blank rows still appear. – iht Apr 23 '13 at 15:20
  • I've added the code which includes my effort to re-open the newly created document. Does it look correct? Unfortunately the blank rows still occurs intermittently. Like before, re-launching the app after killing it fixes the issue, but obviously that's not acceptable. – iht Apr 23 '13 at 17:46
  • IMO, you are losing locality of reference benefit by defining your blocks as variables. Anyway, it looks somewhat reasonable. Are you sure you are waiting for the asynchronous callback to arrive before you try to populate the document? Personally, I do not set the document property until the document is actually open and ready to go... that prevents premature use. – Jody Hagins Apr 24 '13 at 01:35
  • Hi Jody thanks again for your response. I can't see a flaw to the logic in the code as far as I could tell - everything is done in onDocumentReady. Is it at all possible for you to post snippets of code to illustrate how you do it? I'm just at a loss with this. Thanks again. – iht Apr 24 '13 at 07:35
  • I think your issues are elsewhere, not with how the document is opened. – Jody Hagins Apr 24 '13 at 09:00
  • Not that I don't agree with you, it's just that the pattern shows that the blank rows problem only occurs when the app runs for the first time. Subsequently it works fine. Any ideas on what this could be? – iht Apr 24 '13 at 15:22
  • You have to do more debugging to find what is happening in your particular circumstance. Without code of how you are handling the update, all I can do is guess that you are making the common mistake of using the MOC before it is completely ready. – Jody Hagins Apr 24 '13 at 15:27