Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

MrFusion

macrumors 6502a
Original poster
Jun 8, 2005
613
0
West-Europe
Hi everyone

I have a bunch of apps with pretty much the same coredata structure. A lot of common code can be placed in a subclass of NSManagedObject (CommonManagedObject). Seems ideal for a framework. This works fine, but now I want to verify during startup if the NSManagedObjectModel is implemented correctly. Every entity that uses CommonManagedObject, either directly or via a subclass, should have the same minimum set of common properties (e.g. "title").

The code below works fine and I can use the CommonManagedObject and framework. I can identify entities that have "CommonManagedObject" as class.
However I don't know how to identify those entities that are a subclass of CommonManagedObject. "CommonManagedObject" in this is case is nowhere defined in the model and therefore doesn't show up.
It also doesn't show up via the superentity since these particular entities have no superentity.
I can determine the class of the entity but the code crashes when trying to determine the superclass.

This all happens when the app hasn't finished loading yet. So there is no NSManagedObjectContext yet or any other instances.

Thanks!

Code:
+(void) load
{
	[super load];
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
	if (![CommonManagedObject verifyManagedObjectModel:model])
		NSLog(@"Incorrect use of framework. NSManagedObjectModel does not adhere to requirements for CommonManagedObject");
	[pool release];
}

+(BOOL) verifyManagedObjectModel:(NSManagedObjectModel *) model
{	
	BOOL result = TRUE;
	NSArray *allEntities = [model entities];
	[allEntities enumerateObjectsWithOptions:NSEnumerationConcurrent 
								  usingBlock:^(id entityDescription, NSUInteger idx, BOOL *stop) {
									  NSString *entityClassName = [(NSEntityDescription *)entityDescription managedObjectClassName];
									  if (![entityClassName isEqualToString:@"NSManagedObject"])
									  {
										  if ([entityClassName isEqualToString:@"CommonManagedObject"]) 
										  {
											  NSLog(@"verify: %@",[entityDescription name]);
										  }
										  else 
										  {
#if 0 //crashes
											  Class superClass = class_getSuperclass(NSClassFromString(entityClassName));
											  if ([NSStringFromClass(superClass) isEqualToString:@"CommonManagedObject"]) 
											  {
												  NSLog(@"verify: %@",[entityDescription name]);
											  }											  
#endif										  
										  }										  
									  }					  
								  }];
	return result;
}
 
Last edited:
isKindOfEntity: sounds like it should do what you want:

Code:
NSEntityDescription *ed = [NSEntityDescription entityForName:@"CommonManagedObject"
                                      inManagedObjectContext:model];
		
if ([entityDescription isKindOfEntity:ed]) {
    NSLog(@"valid");
}
 
isKindOfEntity: sounds like it should do what you want:

Code:
NSEntityDescription *ed = [NSEntityDescription entityForName:@"CommonManagedObject"
                                      inManagedObjectContext:model];
		
if ([entityDescription isKindOfEntity:ed]) {
    NSLog(@"valid");
}

Thanks for the suggestion, but commonManagedObject doesn't have to be an Entity in the model and thus doesn't necessarily has an NSEntityDescription.
BTW, you mixed up NSManagedObjectContext with NSManagedObjectModel. There is at this stage no NSManagedObjectContext yet.
 
Indeed, sorry about that. Does this do what you want?

Code:
[NSClassFromString(entityClassName) isSubclassOfClass:[CommonManagedObject class]]
 
solved

Indeed, sorry about that. Does this do what you want?

Code:
[NSClassFromString(entityClassName) isSubclassOfClass:[CommonManagedObject class]]

No apology required! Yes, that does the trick! Thanks! :D
I can't believe I missed that. :eek:

Code:
#define requiredAttributes [NSArray arrayWithObjects:@"title",@"noSuchAttribute",nil] //noSuchAttribute to test failure
#define evaluateAllEntities 1

@implementation CommonManagedObject

#pragma mark - 
#pragma mark framework verification
+(void) load
{
	[super load];
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];	
	NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
	if (![CommonManagedObject verifyManagedObjectModel:model])
		NSLog(@"Incorrect use of framework. NSManagedObjectModel does not adhere to requirements for CommonManagedObject");
	[pool release];
}

+(BOOL) verifyManagedObjectModel:(NSManagedObjectModel *) model
{	
        __block BOOL result = TRUE;
	NSArray *allEntities = [model entities];
	[allEntities enumerateObjectsWithOptions:NSEnumerationConcurrent 
								  usingBlock:^(id entityDescription, NSUInteger idx, BOOL *stop) {
									  NSString *entityClassName = [(NSEntityDescription *)entityDescription managedObjectClassName];  
									  if ( ![entityClassName isEqualToString:@"NSManagedObject"]
										  &&
										#if evaluateAllEntities 
										  //evaluate all Entities evaluateAllEntities
										   ([NSClassFromString(entityClassName) isSubclassOfClass:[CommonManagedObject class]]) 
										#endif
										#if !evaluateAllEntities  
										  //evaluate only Entities with CommonManagedObject as class or superclass
										  ([entityClassName isEqualToString:@"CommonManagedObject"] || ( [NSClassFromString(entityClassName) superclass] == [CommonManagedObject class])) 										  
										#endif  
										  )
									  { 
										  NSArray *allAttributes = [[entityDescription attributesByName] allKeys];											  
										  for (NSString *requiredAttribute in requiredAttributes)
										  {
											  if (![allAttributes containsObject:requiredAttribute]) 
											  {
												  NSLog(@"\"%@\" failed for attribute \"%@\"",[entityDescription name],requiredAttribute);  
												  result = FALSE;
												  *stop = TRUE;
											  } 
										  }										  
									  }					  
								  }];
	return result;
}
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.