Core Data and user interface updates

One of the most common problems for Core Date newbies is updating user interface by using NSArrayController when creating a new core data entity by code (not by simply using [arrayController add:nil])

Here is an example for what I mean by code

- (id)newEntity
{
// Create an entry
id entry = [NSEntityDescription insertNewObjectForEntityForName: "Person"
	inManagedObjectContext: managedObjectContext ];

// Use entry
// ...

return entity;
}

If you are using bindings depended on NSArrayController.selection, this will happen after the newEntity method finishes its work. The processPendingChanges method will process all core data relevant changes including just inserted entities. This will trigger all the KVO stuff which will then update your UI immediately.

- (id)newEntity
{
// Create an entry
id entry = [NSEntityDescription insertNewObjectForEntityForName: "Person"
	inManagedObjectContext: managedObjectContext ];

// This will update the user interface
[managedObjectContext processPendingChanges];

// Use entry
// …

return entity;
}

Fetching CoreData entities using RubyCocoa

Here is a dirty style of fetching CoreData entities with RubyCocoa. This is a minimal CoreData entity

Person Core Data

The findAllPersonWithName method will return an array of Person entities, if any. Otherwise the result is an empty array.

def findAllPersonWithName(personName)
  moc = OSX::NSApp.delegate.managedObjectContext
  entityDescirption =
    OSX::NSEntityDescription.entityForName_inManagedObjectContext("Person", moc)
  request = OSX::NSFetchRequest.alloc.init
  request.setEntity_(entityDescirption)
  predicate = OSX::NSPredicate.predicateWithFormat_("name == '#{personName}'")
  request.setPredicate_(predicate)
  moc.executeFetchRequest_error(request, nil)
end

Found memory leaks caused by Nib files

Well, the title is not really correct. Because the memory leak was produced by myself and I want to share my experience. Maybe someone can find it useful.

The problem is that a NSView object directly dragged into my nib file was never released correctly after finishing the work with the nib file.

Tab Content With View
The File’s owner is a very simple class

@interface MyModule : NSObject {
IBOutlet NSView *contentView;
}
- (NSView*)contentView;
@end

The actual issue is, that the retainCount of contentView is always 1 after releasing File’s owner. Trying to release contentView in the dealloc method of MyModule (something like [contentView release]) does the trick and the contentView was deallocated successfully.

Ok. This is NOT the correct way. contentView is an outlet and should not be released manually. While digging deeper I found out that all top level objects in a nib file (these are what you can see in your IB window like in the screenshot above) have retainCount = 1 by after loading the nib file.

And here is the solution. After loading the nib file you should release all top level objects so that you are the only owner of the top level object. Actually these are only the objects which are connected by outlets.

- (void)loadNibNamed:(NSString*)nibFile owner:(id)owner
{
	NSBundle* aBundle = [NSBundle mainBundle];
	NSMutableArray* topLevelObjs = [NSMutableArray array];
	NSDictionary* nameTable = [NSDictionary dictionaryWithObjectsAndKeys:
		owner, NSNibOwner,
		topLevelObjs, NSNibTopLevelObjects,
		nil];

	if (![aBundle loadNibFile:nibFile externalNameTable:nameTable withZone:nil]) {
		NSLog(@"Warning! Could not load Nib file.\n");
		return;
	}

	// Release the objects so that they are just owned by the array.
	[topLevelObjs makeObjectsPerformSelector:@selector(release)];
}

Additionally you can read Apple’s documentation about loading nib files.