我知道在SO上有类似的问题,但它们都不适用于我。
我正在编写我的第一个iOS应用程序(一个简单的书店应用程序),其模型由Book表和User表组成。他们有一个多对多的关系,称为“purchaseBook”。
Book <--purchasedBooks--> User
我正在使用fetchedResultsController在TableView中呈现这些书籍。
但我无法弄清楚如何渲染“用户数据库中所购买的书籍中的所有书籍”。即如何告诉fetchedresultscontroller迭代在User.purchsedBooks中作为集合出现的Book *对象?
基本上,我希望能够在cellForRowAtIndexPath中执行以下操作:
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell* cell;
cell = [self.tableView dequeueReusableCellWithIdentifier:@"bookPlace" forIndexPath:indexPath];
// Get the book for this indexPath
Book* book = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = book.title;
cell.detailTextLabel.text = book.subtitle;
return cell;
}
这是我的尝试:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"];
request.predicate = [NSPredicate predicateWithFormat:@"ALL purchasedBooks"];
request.sortDescriptors = @[];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
非常感谢!
答案 0 :(得分:0)
你是从错误的方向来的。您应该获取具有与您引用的用户相同的用户的PurchasedBook
个实体,然后获取相关的书籍。
请注意,我将PurchasedBook
视为它自己的正确实体,而不仅仅是隐藏的连接表。您可以在PurchasedBook
实体中添加其他元数据,例如购买日期,价格等。
NSFetchedResultsController
的创建将是:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"PurchasedBook"];
[request setPredicate:[NSPredicate predicateWithFormat@"user == %@", [self currentUser]]];
[self setFetchedResultsController:[[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
BTW,实体应该始终是名义上的单数,而不是复数。请注意此代码中的更改。
使用此FetchedResultsController,您的单元格结构会稍微改变一下:
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell;
//this should be using a static for the identifier. Magic strings are risky
cell = [self.tableView dequeueReusableCellWithIdentifier:@"bookPlace" forIndexPath:indexPath];
//You should make sure your cell is not nil just in case your magic string has a typo
if (!cell) {
//build it by hand here
}
// Get the book for this indexPath
PurchasedBook* purchasedBook = [[self fetchedResultsController] objectAtIndexPath:indexPath];
Book *book = [purchasedBook book];
[[cell textLabel] setText:[book title]];
[[cell detailedTextLabel] setText:[book subtitle]];
return cell;
}
有助于停止将Core Data对象视为表。核心数据不是数据库。它是您的对象模型,恰好能够持久化到数据库。持久性是核心数据的次要功能,而不是主要功能。一旦你在脑海中颠倒了这种观点,这些类型的东西就会变得更容易解决。
但是,能否通过用户访问图书(用户可能拥有100本左右的书籍)而不是从书本(表格?)中比较书籍(对用户)是不是更有效率可能会有50,000个物体?
不,因为您想要查看Books not Users。如果您显示的是用户列表,那么您将获取用户。这是关于获取要显示的数据的书籍。
Book和User之间的关系被描述为&#34;多对多&#34;在问题中。在这种情况下,谓词可能应该是&#34;任何用户==%@&#34;。
马丁指出这是正确的。但是我跳了一步。在这种情况下,您总会发现您想了解有关用户和书籍之间关系的更多信息(购买年份,书籍质量,付费价格等)并最终放置元用户和书之间的对象。我在答案中添加了习惯和经验,因为我怀疑你最终会最终添加它:)