Core Data: Cached Transient Properites

Posted November 1st, 2007 by Chris

In writing HostManager 2.0, I’ve come up against a lot of problems caused by the dark magic that is Cocoa bindings and key-value observing. One of the most troublesome of these has been with transient (calculated) properties.

For example, a Client managed object can get a count of owned domains that are expiring soon. This is a transient propety, accessed through a key of expiringDomains. It simply returns an NSSet which is built from a fetchRequest.

Previously, I was running this fetchRequest each time the key was accessed. This was admittedly inefficient, but seemed functional - at least until you saved the document.

Something crazy happens when a Core Data document is saved - all the objects in a context are released (faulted). There is a good reason for this, as it frees up any memory that was being used to temporarily store the managed objects. However, it caused very strange results to appear in my transient properties; namely, they would all vanish.

Even forcing the fetch request to refresh didn’t pick up any objects from the context (I’m not sure why as I would have expected the faulted objects to be ‘refired’). So I took the plunge and refactored the Client object to cache its expiringDomains value. After some extensive testing and finger-crossing, I’m fairly sure this is the correct way to handle transient relationship properties:

CustomManagedObject.h


@interface CustomManagedObject : NSManagedObject {
ame NSSet *transientRelationship;
}
 
- (NSSet *)transientRelationship;

CustomManagedObject.m


#import "CustomManagedObject.h"
 
@implementation CustomManagedObject
 
- (void)awakeFromFetch
{
ame [super awakeFromFetch];
 
ame // set managed object to observe changes to the context, this is necessary
ame // to monitor changes to the context that occur elsewhere in the app
ame [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refresh:) name:NSManagedObjectContextObjectsDidChangeNotification object:[self managedObjectContext]];
 
ame // clear the cache after managed object is fetched into the context
ame if( transientRelationship != nil )
ame [transientRelationship release], transientRelationship = nil;}
 
- (void)refresh:(NSNotification *)notification
{
ame // ... perform check to see if update is neccessary, assume it is...
 
ame if( refreshNeeded ) {
ame if( expiringDomains != nil )
ame gDomains release], expiringDomains = nil;
ame }
}
 
- (NSSet *)transientRelationship
{
ame [self willAccessValueForKey:@"transientRelationship"]
ame
ame if( transientRelationship == nil ) {SFetchRequest *aFetchRequest = [[[NSFetchRequest alloc] init] autorelease];
 
ame [aFetchRequest setEntity:[NSEntityDescription entityForName:@"DestinationEntity" inManagedObjectContext:[self managedObjectContext]]];
 
ame // optionally, set a predicate, e.g. owner == self
ame [aFetchRequest setPredicate:[NSPredicate predicateWithFormat:@"predicateString"]];
 
ame NSArray *results = [[self managedObjectContext] executeFetchRequest:aFetchRequest error:nil];
 
ame transientRelationship = [[NSSet setWithArray:results] retain];
ame }
ame
ame [self didAccessValueForKey:@"transientRelationship"]
 
ame return transientRelationship;
}

Tags: , , , , , ,
Posted in HostManager, Programming | No Comments »

Unfaulting Core Data Objects After Load

Posted October 25th, 2007 by Chris

Hours of searching for an answer were beginning to lead me to the conclusion that it was impossible to unfault transient properties of an NSManagedObject after loading them from a datafile.

The Problem: A ’smart’ group to show expiring domains based on their (transient, calculated) isExpiring property worked until the document was saved. On saving, the objects in the context became faults and the smart group no longer worked. This was also true of re-loading a saved document - the domain’s isExpiring property would not be unfaulted.

ame

The Solution: It’s a horrible solution, but seemingly the only way to get the faults to fire (calling [domain will/didAccessValueForKey:@"isExpiring"] did nothing). On awakening the smart group from a fetch, a quick NSFetchRequest is created to fetch all the Domain objects and unfault their @”data” propety. This is no doubt a dirty piece of code, but seems to force the calculated properties to be unfaulted.


- (void)awakeFromFetch
{
ame [super awakeFromFetch];
ame [self commonAwake];
ame
ame NSError *error;
ame NSFetchRequest *fr = [[[NSFetchRequest alloc] init] autorelease];
ame [fr setEntity:[[self fetchRequest] entity]];
ame
ame NSArray *results = [[self managedObjectContext]
ame SEnumerator *enumerator = [results objectEnumerator];
ame id object;
ame
ame while( object = [enumerator nextObject] ) {
ame NSLog( [object valueForKey:@"domainName"] );
ame [object willChangeValueForKey:@"data"];
ame [object didChangeValueForKey:@"data"];
ame }
}

With this now working, I can finally continue implementing the business logic in HM2.0, and stop worrying about the intricacies of Core Data and the dark art of Bindings.

Tags: , , , , , ,
Posted in HostManager, Programming | No Comments »

Catching up

Posted October 2nd, 2006 by Chris

It’s been a long time since my last post, so I thought I’d try to catch up on whats happening. With Uni life behind me (although not forever…see below), I’m working away on a number of commercial projects, some of which are Web based and a couple of mobile projects that I’ll soon hopefully be able to publish.

HostManager 2.0 Alpha

I’m also working hard at trying to get HostManager 2.0 going. Trying is the key word though - Cocoa seems to have got a lot harder, and why are bindings so difficult to debug?! I’ve lost count of the number of times I’ve started a new test project in XCode. Finally, though, these painful non-starter projects have given way to a working (albeit very early-stages) app. HostManager will also get a nice new website as well, as I fear the existing one is looking somewhat dated…

Also pushing the blog down the list of priorities, I carried out a short J2ME training course a couple of weeks ago, and am now preparing similar coding workshops for iDat. The J2ME workshops gave me some good experience and feedback on delivering code-based workshops that I’m sure will be useful for the iDat workshops next year.

So, to kick-start the blog again, I’ve treated the site to a new theme, and am considering finishing some of the half-written posts that are littering my drafts folder…

Posted in Business, HostManager, Personal, Programming | No Comments »

J2ME Workshop - Take 1

Posted August 22nd, 2006 by Chris

This week, I’m conducting a small training workshop to introduce Wireless development to a few people. The course is designed to highlight some of the opportunities that wireless development allows, and how the J2ME platform can take advantage of those opportunities.

The basics introduced in the course are what I have learnt during and since the development of Toupix, and also help me to improve my knowledge further. I’m also using some of the frameworks developed for the course as part of ongoing research of mobile applications, the results of which I hope will grow into a full product for Pebbledot.

Talking of which, the commercial website is so close to launch now, just a few app issues to sort out with the online purchasing and licence generation for HostManager. I’m looking for some good Web-based project management software for HostManager 2.0’s development as I have decided to be a lot more organised for this major release!

Any suggestions welcome…

Posted in Business, HostManager, Personal | No Comments »

HostManager 1.16

Posted July 14th, 2006 by Chris

Despite big plans to freeze development of the 1.x line, and concentrate on rapidly delivering 2.0, I have found a spare moment to sort out a couple of irritations with the current build. As a result, HostManager 1.16 has now been released with the following little fixes:

    ame
  • Fixed expired trial period window to allow licensing post-trial period.
  • ame

  • Threaded backup to .Mac to prevent lockups.
  • ame

  • Threaded synchronisation with iCal to prevent lockups.
  • ame

  • Fixed/Improved Inspector interface window.
  • ame

  • Fixed/Improved Inspector interface window.
  • ame

  • Fixed payments destination for purchasing HostManager.
  • ame

  • Updated Sparkle framework to Version 1.0

The latest version can be downloaded using the Sparkle updater, or directly here. Version 2.0 is progressing slower than anticipated due to a number of other projects, moving house, setting up business, etc. etc. Lame excuses…

Posted in HostManager, Personal | No Comments »