Core Data addObject 一对多关系

Posted

技术标签:

【中文标题】Core Data addObject 一对多关系【英文标题】:Core Data addObject one-to-many relationShip 【发布时间】:2013-09-30 21:15:15 【问题描述】:

我尝试将对象添加到我的核心数据模型中。但是,当我尝试显示它们时,它们并不存在。我正在使用类别作为助手。

+ (Project *)createProjectWithDictionary:(NSDictionary *)dic inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext 

    Project *project = nil;

    // Build a fetch request to see if we can find this Flickr photo in the database.
    // The "unique" attribute in Photo is Flickr's "id" which is guaranteed by Flickr to be unique.

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Project"];
    request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]];
    request.predicate = [NSPredicate predicateWithFormat:@"title = %@", [dic[kTagProjectTitle]description]];

    // Execute the fetch

    NSError *error = nil;
    NSArray *matches = [managedObjectContext executeFetchRequest:request error:&error];

    // Check what happened in the fetch

    if (!matches || ([matches count] > 1))   // nil means fetch failed; more than one impossible (unique!)
        // handle error
     else if (![matches count])  // none found, so let's create a Photo for that Flickr photo
        project = [NSEntityDescription insertNewObjectForEntityForName:@"Project" inManagedObjectContext:managedObjectContext];
        NSLog(@"Encontrado Primera vez");

        project.projectId = [NSNumber numberWithInt:[[dic valueForKey:kTagProjectId] intValue]];
        project.title = [dic valueForKey:kTagProjectTitle];
        project.estimatedPrice = [NSNumber numberWithInt:[[dic valueForKey:kTagProjectEstimatedPrice] floatValue]];
        NSMutableArray *tags = [[NSMutableArray alloc] init];
        tags = [dic objectForKey:kTagProjectsTags];

        NSMutableSet *tagSet = [[NSMutableSet alloc]init];
        for (NSDictionary * tagDic in tags)
            NSString *tagName = [tagDic objectForKey:kTagProjectTagName];
            Tag *tag = [Tag insertTagName:tagName inManagedObjectContext:managedObjectContext];
            [project addTagsObject:tag];
        

       // [project addTags:tagSet];

我尝试过使用带有 addObject:(NSSet *tag) 的 NSMutableSet 以及 addTagObject 并且我在 NSLog 中有相同的输出。

            for( Tag *tag in project.tags)
                NSLog(@"TAG TITLES %@", tag.name);  
            
       2013-09-30 23:03:36.003 Prototype[28959:c07] TAG TITLES ios
       2013-09-30 23:03:36.004 Prototype[28959:c07] TAG TITLES Windows Phone
    

然后,当我尝试在单元格中显示它们时。我有一个新的 NSLog,这是输出。为什么在第一个 NSLog 中我可以看到它们,而不是在 cellForRowAtIndexPath 方法中?

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
   Project *project = (Project *)[self.data objectAtIndex:indexPath.row];
   NSLog(@"TITLE %@", project.tags);

输出

 TITLE Relationship 'tags' on managed object (0x7c60ba0) <Project: 0x7c60ba0> (entity: Project; id: 0x7c60be0 <x-coredata:///Project/tE9F74F99-04BC-43CC-BD68-F435712B3B3C9> ; data: 

    estimatedPrice = 1999;
    projectId = 418;
    tags =     (
    );
    title = "Aplicaci\U00f3n IOS";
    "yp_desc" = nil;
) with objects (
)


【问题讨论】:

[Tag insertTagName:tagName inManagedObjectContext:managedObjectContext]; 是否在呼叫insertNewObjectForEntityForName:inManagedObjectContext: 是的,[Tag insertTagName:tagName inManagedObjectContext:managedObjectContext]; 几乎和[项目创建.....但是明显改变变量的方法相同 【参考方案1】:

很可能您在添加标签后没有保存上下文。

【讨论】:

添加标签对象后保存上下文。我得到这个输出:“ tags = 没关系。这意味着实际上并没有从数据库中获取数据——它会在您访问对象的某些属性后被获取。立即设置您的手机,一切正常 我已经把这个放在 NSLog 中的 cellForRowAtIndexPath:int i = 0; for( Tag *tag in project.tags) NSString *tagName = tag.name; NSLog(@"i value = %d", i); NSLog(@"TITLE %@", tagName); 并且没有输出,这意味着我的上下文中没有任何标签。 1) 你在某处覆盖了 project.tags。 2)您在某处删除 Tag 对象。此外,您可以在调试中检查 tags 属性被清除的确切位置 这很奇怪。我将这个数组用于我的行- (void)refreshData:(NSDictionary *)newData managedObjectContext = [YPDataSingleton context]; for (NSDictionary *projectDic in newData) [data addObject:[Project createProjectWithDictionary: projectDic inManagedObjectContext:managedObjectContext]]; [self.tableView reloadData]; 以及在从服务获取标签到核心数据后使用这个数组` [project addTags:tagSet]; [ managedObjectContext 保存:无]; `【参考方案2】:

我建议你使用 Magical Record 框架 (https://github.com/magicalpanda/magicalrecord),它让 Core Data 管理变得更加容易!

另一方面,如果你想继续没有它,我会尝试改变:

 + (Project *)createProjectWithDictionary:(NSDictionary *)dic inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext 

    Project *project = nil;

    // Build a fetch request to see if we can find this Flickr photo in the database.
    // The "unique" attribute in Photo is Flickr's "id" which is guaranteed by Flickr to be unique.

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Project"];
    request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]];
    request.predicate = [NSPredicate predicateWithFormat:@"title = %@", [dic[kTagProjectTitle]description]];

    // Execute the fetch

    NSError *error = nil;
    NSArray *matches = [managedObjectContext executeFetchRequest:request error:&error];

    // Check what happened in the fetch

    if (!matches || ([matches count] > 1))   // nil means fetch failed; more than one impossible (unique!)
        // handle error
     else if (![matches count])  // none found, so let's create a Photo for that Flickr photo
        project = [matches lastObject];
        NSLog(@"Encontrado Primera vez");

        //Makes that only if you want to rehydrate your saved object. At other way I am not sure what yo want to do here :S
        project.projectId = [NSNumber numberWithInt:[[dic valueForKey:kTagProjectId] intValue]];
        project.title = [dic valueForKey:kTagProjectTitle];
        project.estimatedPrice = [NSNumber numberWithInt:[[dic valueForKey:kTagProjectEstimatedPrice] floatValue]];
        NSMutableArray *tags = [[NSMutableArray alloc] init];
        tags = [dic objectForKey:kTagProjectsTags];

        for (NSDictionary * tagDic in tags)
            NSString *tagName = [tagDic objectForKey:kTagProjectTagName];
            Tag *tag = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:managedObjectContext];
            //TODO: populate tag object using tagDic
            [project addTagsObject:tag];
        

如果您尚未保存当前上下文,请记住在同一上下文中进行提取;)

【讨论】:

以上是关于Core Data addObject 一对多关系的主要内容,如果未能解决你的问题,请参考以下文章

设置一对多关系 Core Data 和 Magical Record

Core Data 获取请求与 NSFetchedResultsController 的一对多关系

Core Data 获取一对多关系的数据

Core Data 中一对多关系的正确 NSPredicate 格式

如何管理 Core Data 中的一对多关系?

如何为一对多关系正确配置 Core Data 数据模型和 NSManagedObject?