【问题标题】:IOS Core Data Cardinality issueIOS核心数据基数问题
【发布时间】:2014-05-18 09:46:03
【问题描述】:

我正在使用 TableViews 和 Core Data 编写一个简单的应用程序,它显示第一级的学生列表,当单击单元格时,它会显示学生所修课程的名称。我将student->courses设置为toMany,将courses->student设置为toOne。这就是我将 Student 实体传递给课程视图控制器以使用其 managedObjectContext 的方式:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    Student *info = [_fetchedResultsController objectAtIndexPath:indexPath];
    CoursesTableViewController *courseViewController = [[CoursesTableViewController alloc] initWithStudentInfo:info];
    [self.navigationController pushViewController:courseViewController animated:YES];
}

这就是我在课程视图控制器中创建课程的方式(我只想要三个如下命名的课程,numberofrow 应该保证这一点):

- (void)viewDidLoad
{
    [super viewDidLoad];

    id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][0];
    int numberofrow = [sectionInfo numberOfObjects];
    NSLog(@"%d",numberofrow);
    NSLog(@"%d",[self.fetchedResultsController sections].count);
    if(numberofrow <=2){
        NSLog(@"creating courses");
        [self insertNewObject:@"comp319"];
        [self insertNewObject:@"comp314"];
        [self insertNewObject:@"comp316"];
    }
}

- (void)insertNewObject:(NSString *) str{

    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
    NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];


    [newManagedObject setValue:str forKey:@"course_name"];

    NSError *error = nil;
    if (![context save:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

我如何在课程视图控制器中创建 fetchedResultsController:

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Courses" inManagedObjectContext:self.studentInfo.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"course_name" ascending:NO];
    NSArray *sortDescriptors = @[sortDescriptor];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.studentInfo.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}

最后的问题是,当我创建第一个学生并单击它时,上面的课程视图控制器的 viewDidLoad 中的 NSLog 会打印“创建课程”,但是当我创建第二个学生时它不会,并且 numberofrow 也会在它的位置打印 3应该打印 0,因为它是一个新的学生实例。

感谢您的帮助。

【问题讨论】:

  • CoursesTableViewController中创建fetchedResultsController时的NSPredicate是什么?
  • 我复制了上面的全部内容。

标签: ios core-data


【解决方案1】:

替换

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Courses" inManagedObjectContext:self.studentInfo.managedObjectContext];
[fetchRequest setEntity:entity];

// my comment : entity here has to be your student name, why 'course'
// and also replace your search key from 'yourCourseNameKey' with 'yourStudentNameKey'
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Your Student Name" inManagedObjectContext:self.studentInfo.managedObjectContext];
[fetchRequest setEntity:entity];

您需要获取学生数量,但您查询的是课程数量

【讨论】:

  • 编译器要求 sortDescriptors。
  • 对不起,我的意思是:您仍然使用 sortDescriptor,但您应该将键“course_name”替换为“yourStudentNameKey”
【解决方案2】:

您没有在提供给 fetched 请求控制器的 fetch 上设置谓词,因此您不会为所选学生搜索课程并在他们不存在时创建课程。无论如何,这并不是理想的(并且不会起作用,因为您没有在学生和所有课程之间建立关系)。

因此,您很可能应该拥有一组课程和一组学生。这种关系应该是多:多,因为一门课程确实有多个学生,每个学生都修多门课程(或者无论如何都可以)。

现在,您的学生和课程将被“预先”创建,然后您的视图控制器只需处理获取、显示和连接(建立关系)对象。

【讨论】:

  • 感谢您的回复。我将其设置为很多:很多。然而,在创建第一个学生之后,下一个学生没有打印 NSLog(@"creating courses") 这让我认为他们没有创建新的学生-课程关系,而是覆盖了第一个学生。
  • 你刚刚改变了关系吗?因为我的回答说你应该改变你的方法,而不是创建多个课程副本......
  • 我真的不确定如何将表格视图的级别与 Core Data 关联起来。配置 .xcdatamodeld 不足以以“学生参加这些课程并且课程由这些学生参加”的形式给出结果。我能找到的教程都没有解释这种情况。
  • 您理解有多位学生和多门课程的概念,并说一部分学生正在学习一门课程,而另一部分(可能重叠)的学生正在学习另一门课程?
  • 不,所有学生都在学习相同的三门课程,当他们点击课程名称时,他们应该看到他们在该课程中的成绩。然而目前,由于课程编号是固定的和预定义的,它们看起来还不错,但是当用户编辑学生的成绩时,它会反映到他的其他课程成绩以及其他学生的成绩。抱歉,我一开始试图简化问题,但结果搞混了。
猜你喜欢
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-20
  • 2011-07-03
相关资源
最近更新 更多