2013-05-02 35 views
3

我已经把标题中的下一步,因为这不是我的上一个问题几乎完全相同的标题相同的问题。魔法记录导入(下一步)

我有一个Person实体。

Person 
-------- 
name  - mappedKeyName: FullName 
email  - mappedKeyName: EmailAddress 
personID - mappedKeyName: Id 
-------- 
photos 

和一个Photo实体。

Photo 
-------- 
image 
createDate - mappedKeyName: Date 
photoID - mappedKeyName: Id 
-------- 
owner (type Person) - mappedKeyName: UserId - relatedByAttribute: personID 

有一些涉及到Person过其他对象将它们的JSON之际,所以......

{ 
    ObjectId : blah, 
    Owner : { 
     Id : 12345asdfg, 
     FullName : Oliver, 
     EmailAddress : [email protected] 
    } 
} 

有了这个JSON我的设置可与进口。任何不存在的人员记录(包含Id)都会被创建。任何存在的都会更新。

然而,照片JSON对象就这样产生了...

{ 
    Id : thisIsThePhotoID, 
    Date : today, 
    UserId : 12345asdfg 
} 

当物体下来这样当它到达的人进口的神奇纪录进口停止。

代码崩溃在...

- (id) MR_relatedValueForRelationship:(NSRelationshipDescription *)relationshipInfo 
{ 
    NSString *lookupKey = [self MR_lookupKeyForRelationship:relationshipInfo]; 
    return lookupKey ? [self valueForKeyPath:lookupKey] : nil; // it stops here. 
} 

lookupKey值是@ “PERSONID”。

打印出来relationshipInfo在断点处使...

$6 = 0x1fd695e0 (<NSRelationshipDescription: 0x1fd695e0>), 
    name owner, 
    isOptional 0, 
    isTransient 0, 
    entity Photo, 
    renamingIdentifier owner, 
    validation predicates(), 
    warnings(), 
    versionHashModifier (null) 
    userInfo { 
     mappedKeyName = UserId; 
     relatedByAttribute = personID; 
    }, 
    destination entity Person, 
    inverseRelationship photos, 
    minCount 1, 
    maxCount 1, 
    isOrdered 0, 
    deleteRule 1 

我真的不知道为什么,这是行不通的。我没有收到任何明显的错误报告。

回答

17

MagicalRecord不能与此JSON格式自动映射的关系:

{ 
    Id : thisIsThePhotoID, 
    Date : today, 
    UserId : 12345asdfg 
} 

为了MagicalRecord映射到Person对象的关系,它会是在JSON的对象,以及,例如:

{ 
    Id : thisIsThePhotoID, 
    Date : today, 
    User : { 
     UserId : 12345asdfg 
    } 
} 

这样MagicalRecord知道这是一个对象,它会做适当的查找在现有数据库中的记录Person与上面的ID和映射关系。

因此,这有两个问题。如果您无法更改JSON输出,您必须在Photo上创建一个您自己手动映射关系的类别类。第二个问题之后我会做到这一点。

第二个问题是,上面的JSON格式假定您已经解析了用户并将记录存储在数据库中。如果你还没有MagicalRecord,将创建一个新的Person记录与上述ID,但由于没有其他属性存在该对象(注意UserId键是字典中唯一的属性)它将是相当空的,不包括名称和电子邮件地址。您可以随时扩展您的JSON(如果你有这种可能性),包括照片字典里面的那些属性,以及在人物辞典:

{ 
    Id : thisIsThePhotoID, 
    Date : today, 
    User : { 
     UserId : 12345asdfg, 
     FullName : Oliver, 
     EmailAddress : [email protected] 
    } 
} 

的JSON有效载荷相当小,所以它不会伤害做如果你可以的话。另外,如果数据库中不存在记录,它将只创建一个新的Person记录。

然后进行手动映射。如果您无法将JSON更改为上述格式,则必须手动覆盖关系映射,因为JSON未按照MagicalRecord映射的方式进行准备。

Photo创建一个类别类Photo+Mapping.h/.m。我喜欢为这些坚持+Mapping。然后这个类在头文件和实现文件中应该是Photo (Mapping),你很好。

MagicalRecord有许多实例方法可以覆盖(见MagicalRecord的作者写的this article on MagicalRecord importing的后半部分),其中有import<;attributeName>;:import<;relationshipName>;:。在类本身上还有一个willImport:,didImport:shouldImport:方法,它允许您覆盖任何映射。

对于您的情况,您可以使用import<;relationshipName>;:shouldImport:。我将这两个因素考虑在内,因为根据您是否已映射了所有对象Person以及它们是否可用于Photo对象上的关系映射,有一个好处。

下面是你可以做的事情的例子(如果你愿意的话,你可以选择合并其中的一些),这样做不会伤害。这里注意:总是在覆盖映射时使用当前的NSManagedObjectContext(通过self.managedObjectContext可以通过MagicalRecord方便地访问),否则最终会出现上下文问题。

一定要导入联系人:

#import "Photo+Mapping.h" 
#import "Person.h" 

// Assuming you only want to import the Photo object if you already have a Person stored this is a great method to tell MagicalRecord whether to continue with importing or not 
-(BOOL)shouldImport:(id)data { 
    Person *person = [Person findFirstByAttribute:data[@"UserId"] value:@"personID" inContext:self.managedObjectContext]; 
    if (!person) { 
     // no Person object exists so don't import the Photo object - again this is up to you since you might want to create the record if not 
     return NO; 
    } 
    // you can set the relationship here (you might as well) or use the importPerson: method below (doing a second lookup, which is unnecessary at this point) 
    [self setPerson:person]; 
    return YES; 
} 

// If you use this method you're doing the lookup to check whether a record exist when MagicalRecord is trying to map the Person relationship 
-(void)importPerson:(id)data { 
    Person *person = [Person findFirstByAttribute:data[@"UserId"] value:@"personID" inContext:self.managedObjectContext]; 
    if (!person) { 
     // if no Person record exists for the associated UserId, you should create one (or not - if you choose not to, it's wise to throw away this Photo object) 
     person = [Person createInContext:self.managedObjectContext]; 
     [person setPersonID:data[@"UserId"]]; 
    } 
    // set the relationship 
    [self setPerson:person]; 
} 

// finally you can also use the following method when MagicalRecord is done mapping and get rid of the Photo object if the Person relationship is nil: 
-(void)didImport:(id)data { 
    if (!self.person) { 
     [self deleteInContext:self.managedObjectContext]; 
    } 
} 

希望这有助于!如果您有任何问题,请告诉我。

+0

优秀的答案!非常感谢。你是第一个说这种格式导入不起作用的人。 (我以前的三个问题都有答案,都是“它首先正常工作”)。我明天回去工作,所以我会着手实施您的解决方案。再次感谢。 – Fogmeister 2013-05-06 18:26:40

+0

@Fogmeister让我知道它是怎么回事,如果您有任何问题我可以帮忙。 – runmad 2013-05-07 21:12:22

+0

@Fogmeister我很好奇它是否帮你解决了这个问题? – runmad 2013-05-09 20:46:34