1

I have added a category to my NSManagedObject IBCompany, which should retrieve a specific time period, which is one of the IBCompany's relationships, based on a simple date comparison.

When I run the following code, the NSArray sortedFinPeriodsDesc contains the faulted periods in the correct sorted order. However, when accessing them in the for each loop, each of the periods returns nil for its attributes, and in particular, nil for its EndDate. For this reason my method lastReportedPeriodforDate always returns nil, which is an error.

#import "IBCompany+FinstatAccessors.h"

@implementation IBCompany (FinstatAccessors)

NSArray *sortedFinPeriodsDesc;

- (IBFinPeriod*)lastReportedPeriodforDate:(NSDate*)date;
{
    if ( !sortedFinPeriodsDesc ) {
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"EndDate" ascending:NO];
        sortedFinPeriodsDesc = [self.finperiod sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
        }   
    IBFinPeriod *lastPeriod;
    for (IBFinPeriod *finPeriod in sortedFinPeriodsDesc) {
        if ( [finPeriod.EndDate compare:date] == NSOrderedAscending ){ // finPeriod.EndDate < date
            lastPeriod = finPeriod;
            break;
        }
    }
    return lastPeriod;
}

However, when replacing the first lines (lazy instantiation) in the method by removing the if clause and always instantiating and sorting NSArray sortedFinPeriodsDesc, the code works fine.

Hence, I have a couple of questions:

  • What is the error in my code? How does affect lazy instantiation faulting?
  • Would you recommend defining the NSArray sortedFinPeriodsDesc as transient attribute and sorting it in awakeFromFetch instead?
  • What would be the best option in your view?

Thank you very much for your help!

AlexR
  • 5,514
  • 9
  • 75
  • 130
  • May be an issue converting the NSManagedObject in the array to your class IBFinPeriod..? Also double check the awakefrominsert and such. – Vaibhav Garg Jul 24 '12 at 09:35
  • Is that array really defined "floating around" in the implementation section? – jrturton Jul 24 '12 at 09:53
  • Vaibhav, I didn't use awakeFromInsert yet. I use only the code provided in my question above. Jrturton, what do you mean by "floating around"? – AlexR Jul 24 '12 at 12:01
  • I mean, you've just written it on a line on its own, not inside braces which is where ivars are normally declared? – jrturton Jul 24 '12 at 12:03
  • This is the only way I got it working. If I put it in the interface declaration `@interface IBCompany (FinstatAccessors) { @private NSArray *sortedFinPeriodsDesc, *sortedFinPeriodsAsc; }` I get the error message `Ivars may not be placed in categories`. – AlexR Jul 24 '12 at 12:07
  • You're not making it an ivar doing it that way, that's the problem. See http://stackoverflow.com/questions/2571518/class-variable-defined-at-implementation-rather-than-interface – jrturton Jul 24 '12 at 12:18
  • Thank you for pointing me to this error. I did not know that I do not create ivars. How can I create an ivar or property in an category (like the one described in the question) or would I need to declare it as a transient attribute (since it is a NSManagedObject). – AlexR Jul 24 '12 at 12:24

1 Answers1

1

The "lazy loading" smacks of a premature optimisation. Particularly the way you've implemented it, you aren't actually using an instance variable, but a global variable (see here for details), meaning that each object isn't holding its own version of the array.

I would suggest having the array local and generating it each time it is required. If this impacts performance, you can look at other methods, but even with the ivar problem above resolved, you are going to hit problems if the periods set is updated - your array is now out of date.

You haven't said how many times your objects are being asked for this period, or how many objects, or how many periods, so it is difficult to give more specific advice.

A fetched property might be a more efficient way of getting the period, but I don't have enough experience with them to help in your specific case.

Community
  • 1
  • 1
jrturton
  • 118,105
  • 32
  • 252
  • 268