views:

121

answers:

2

Hi there.

I am trying to save the dimensions of my document window through Core Data. I have used the following code to save the width and height:

managedObjectContext = [[[NSDocumentController sharedDocumentController] currentDocument] managedObjectContext];

NSSize windowSize;
windowSize.width = documentWindow.frame.size.width;
windowSize.height = documentWindow.frame.size.height;

SizeInfo *windowInfo = (SizeInfo *)[NSEntityDescription insertNewObjectForEntityForName:@"SizeInfo" inManagedObjectContext:managedObjectContext];

[windowInfo setWidth:[NSString stringWithFormat:@"%f", windowSize.width]];
[windowInfo setHeight:[NSString stringWithFormat:@"%f", windowSize.height]];

NSLog (@"Width = %f, Height = %f", windowInfo.width, windowInfo.height);

I use the following code to fetch the same information:

managedObjectContext = [self managedObjectContext];

NSArray *array = [MyDocument objectsForEntityNamed:@"SizeInfo" inContext:managedObjectContext];
NSLog (@"%@", [array objectAtIndex:0]);

The fetch method on the second line calls the following method in my code:

+ (NSArray *)objectsForEntityNamed:(NSString *)name inContext:(NSManagedObjectContext *)context
{
NSEntityDescription *entity = [NSEntityDescription entityForName:name inManagedObjectContext:context];

NSFetchRequest *req = [[NSFetchRequest alloc] init];    
[req setEntity:entity];

NSError *error = nil;

NSArray *array = [context executeFetchRequest:req error:&error];

if (array == nil)
{
    NSException *exception = [NSException 
                              exceptionWithName:self 
                              reason:[error localizedDescription] 
                              userInfo:nil];


    [req release];
    [exception raise];
}

[req release];

return array;
}

When I try to fetch the information, I receive the following error:

*** -[NSArray objectAtIndex:]: index (0) beyond bounds (0)

Upon debugging, it appears I have an initialised array with 0 objects in it.

Does anyone see anything here I might need to fix in order to get things working?

Thanks in advance. Ricky.

A: 

Yes, but does this work with Document Based Applications also? I can't see how it can.

Mathieu Tozer
No, it won't. User defaults are per-application; they won't work for a per-document setting.
Peter Hosey
+1  A: 

First, you're storing numbers as strings when Core Data natively supports numbers.

Second, using a class method to do the fetch instead of an instance method is weird. An instance method could use NSPersistentDocument's -managedObjectContext instead of requiring an argument that passes one in:

- (NSArray *)objectsForEntityWithName:(NSString *)name
{    
    NSManagedObjectContext *context = [self managedObjectContext];
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];    
    [request setEntity:[NSEntityDescription entityForName:name
                                   inManagedObjectContext:context]];

    NSError *error = nil;
    NSArray *results = [context executeFetchRequest:request error:&error];
    if (!results)
    {
        [NSApp presentError:error];
        return nil;
    }

    return results;
}

However, I wouldn't use a generic fetch method like that. Instead, I'd write instance methods for retrieving specific data, such as an -(NSSize)documentWindowSize method that retrieves the data from the context and returns it as an NSSize structure for me.

It's hard to precisely diagnose why your fetch request is returning zero results without know when these pieces of code are being called. Where and when is the insertion code and fetching code running in your program? I assume the size saving code is getting called outside the NSPersistentDocument subclass since you're having to go through the shared document controller to get the context.

In any case, I would have your document class register for window size change notifications from its document window and save the new size in its listening method.

Preston