将核心数据对象传递给新的表视图控制器,但使用对象的关系在新的视图控制器中显示该数据

时间:2013-11-19 19:59:03

标签: ios objective-c core-data nsfetchedresultscontroller nsfetchrequest

我遇到了一个未捕获的异常,在运行时发送了错误的选择器,在表视图控制器之间传递对象时基于核心数据的应用程序。

我面临的问题(当你阅读这个问题时会更清楚)是我不确定如何引用Core Data Objects的关系而不是调用Object本身。

让我们退一步看看模型,应用程序的前提很简单;允许用户创建具有名称,数量,场合和日期的“交易”。

具有wasGiven属性的交易实体 具有name属性的Person实体 具有title属性的Occasion Entity 具有金额属性的项目实体 事务与Person实体(whoBy),Occasion Entity(场合)的链接以及Item Entity(itemType)的链接有关系。

编辑:核心数据模型

enter image description here

App是一个简单的2 Tabb-ed表视图控制器 - 第一个选项卡包含所有信息,按日期划分。对于这个TableViewController,我正在使用以下fetchedResultsController代码查看“Transaction Entity”:

- (NSFetchedResultsController *)fetchedResultsController
{
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];

    if (_fetchedResultsController != nil)
    {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];    
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:managedObjectContext];
    fetchRequest.entity = entity;
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"occasion.dateOfEvent" ascending:NO];
    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    fetchRequest.fetchBatchSize = 20;
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"occasion.dateOfEvent" cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

第二个标签只包含“名称”信息。有一个加号按钮,当用户按下它时,它们会显示一个模态视图,以添加名称,场合,数量和日期。他们按保存并将其保存到核心数据数据库。所以第二个选项卡只显示名称(我必须做很多工作才能使这一点工作,所以它不会重复)但是第二个表视图的fetchedResultsController是:

- (NSFetchedResultsController *)fetchedResultsController
{
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];

    if (_fetchedResultsController != nil)
    {
        return _fetchedResultsController;
    }
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:managedObjectContext];
    fetchRequest.entity = entity;
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;        _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

当我选择一行时,会调用prepareForSegue方法:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{

    NSIndexPath *indexPath = [self.personTableView indexPathForCell:sender];
    Transaction *selectedTransaction = [self.fetchedResultsController objectAtIndexPath:indexPath];
    if ([segue.identifier isEqualToString:@"Selected Person Segue"])
    {
        EnvylopeSelectedPersonTableViewController *selectedPerson = [segue destinationViewController];

        [selectedPerson setTransaction:selectedTransaction];
    }
}

所以在SelectedTableView中,我显然有一个属性来保存:

@property (nonatomic, strong) Transaction *transaction;

使用setter将其标题设置为所选名称。

我在这个新的Table视图中想要的是显示该人的历史 - 与原始的第一个标签非常相似,但只是为这个人定制,这就是为什么我认为我会使用谓词。

选择的表视图fetchedResultsController是:

- (NSFetchedResultsController *)fetchedResultsController
{
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];

    if (_fetchedResultsController != nil)
    {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:managedObjectContext];
    fetchRequest.entity = entity;


    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"occasion.dateOfEvent" ascending:NO];

    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    fetchRequest.fetchBatchSize = 20;

    fetchRequest.predicate = [NSPredicate predicateWithFormat:@"whoBy.name = %@", self.transaction.whoBy.name];

    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"occasion.dateOfEvent" cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

这是一个例外:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person whoBy]: unrecognized selector sent to instance 0x8b550b0'

我理解为什么会这样;我正在传递一个事务并显示一个事务,但我不能在人员表视图中使用事务,因为它会为人创建重复项(这是我在这里遇到的大问题),所以我怎么能以某种方式解决这个问题呢?我需要在Selected Table View中使用Transaction fetchRequest的原因是因为我需要引用日期,标题和金额,所有这些都与Transaction相关而不是Person的一部分。

对此的任何帮助都将受到大力赞赏!

1 个答案:

答案 0 :(得分:1)

prepareForSegue:中,获取的结果控制器不会获取 Person 对象 交易对象。因此

Transaction *selectedTransaction = [self.fetchedResultsController objectAtIndexPath:indexPath];

实际上是Person(将其转换为Transaction不会改变这一事实)。 所以你应该把它改成

Person *selectedPerson = [self.fetchedResultsController objectAtIndexPath:indexPath];
EnvylopeSelectedPersonTableViewController *selectedPersonVC = [segue destinationViewController];
selectedPersonVC.person = selectedPerson;

其中person是EnvylopeSelectedPersonTableViewController的属性:

@property (nonatomic, strong) Person *person;

显示此人的所有交易的谓词将只是

fetchRequest.predicate = [NSPredicate predicateWithFormat:@"whoBy = %@", self.person];