magicalpanda/MagicalRecord

executeFetchRequest:error: A fetch request must have an entity.

JustinYangJing opened this issue · 0 comments

MagicalRecord Version: 2.3.2
Xcode:8.3.3
Crash iOS Version :8.x ,9.x
Crash Reason:
A fetch request without entity name .

Entity name is generated by the following function when MagicalRecord alloc a fetch request.

  • (NSString *) MR_entityName;
    {
    NSString *entityName;
    if ([self respondsToSelector:@selector(entityName)])
    {
    entityName = [self performSelector:@selector(entityName)];
    }
    if ([entityName length] == 0)
    {
    // Remove module prefix from Swift subclasses
    entityName = [NSStringFromClass(self) componentsSeparatedByString:@"."].lastObject;
    }
    return entityName;
    }

The entity name and the class name (a subclass of NSManagedObject) cant be same in Xcode 8.x.
So just get the class name from the MR_entityName ,not the entity name .
if you create *.xcdatamodeld with Xcode 7.x, entity name and the class name are same , so it could get the correct entity name .
Actually , a new function that is call 'fetchRequest' will be auto generated by Xcode 8.x when you select Xcode menu 'Editor | NSManagedObject Subclass '. MagicalRecord could use this function and generate fetch request.

there is no 'fetchRequest' function if the class (a subclass of NSManagedObject) was generated by Xcode 7.x.

So I fix this bug by hooking MR_entityName function .
create a NSManagedObject category. the following is the code .

+(void)load{
Method m1 = class_getClassMethod([self class], @selector(MR_entityName));
Method m2 = class_getClassMethod([self class], @selector(MR_entityNameHook));
method_exchangeImplementations(m1, m2);
}
+(NSString *)MR_entityNameHook{
if ([self respondsToSelector:@selector(fetchRequest)]) {
NSFetchRequest *request = [self fetchRequest];
return request.entityName;
}
return [self MR_entityNameHook];
}