NSFetchedResultsController 未加载所有条目
NSFetchedResultsController not loading all entires
我有一个简单的应用程序,每个 UITabBar
中有一个 UITabBarController
和 2 个 UITableViewControllers
。第一个 UITableViewController
称为 Videos
,第二个称为 Languages
。
Videos
将仅代表有视频的语言,而语言将显示所有语言。
出于测试目的,我从 AppDelegate 填充核心数据实体。
我的核心数据模型如下:
填充核心数据的方法如下所示:
- (void)loadVideosTab
{
// Here is where we'll load up the Videos tab.
NSManagedObjectContext *context = [self managedObjectContext];
NSString *chinese = @"Chinese";
NSString *dutch = @"Dutch";
NSString *english = @"English";
NSString *french = @"French";
NSString *italian = @"Italian";
NSString *punjabi = @"Punjabi";
NSString *spanish = @"Spanish";
NSString *tamil = @"Tamil - தமிழ்";
Language *language = [NSEntityDescription insertNewObjectForEntityForName:@"Language" inManagedObjectContext:context];
Video *chineseLanguage = (Video *)[Video videoLanguage:chinese inManagedObjectContext:context];
language.videos = chineseLanguage;
Video *dutchLanguage = (Video *)[Video videoLanguage:dutch inManagedObjectContext:context];
language.videos = dutchLanguage;
Video *englishLanguage = (Video *)[Video videoLanguage:english inManagedObjectContext:context];
language.videos = englishLanguage;
Video *frenchLanguage = (Video *)[Video videoLanguage:french inManagedObjectContext:context];
language.videos = frenchLanguage;
Video *italianLanguage = (Video *)[Video videoLanguage:italian inManagedObjectContext:context];
language.videos = italianLanguage;
Video *punjabiLanguage = (Video *)[Video videoLanguage:punjabi inManagedObjectContext:context];
language.videos = punjabiLanguage;
Video *spanishLanguage = (Video *)[Video videoLanguage:spanish inManagedObjectContext:context];
language.videos = spanishLanguage;
Video *tamilLanguage = (Video *)[Video videoLanguage:tamil inManagedObjectContext:context];
language.videos = tamilLanguage;
NSError *error = nil;
if (![context save:&error])
{
// Error
}
}
我在 Video
实体上调用的类别是:
+ (Video *)videoLanguage:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context
{
Video *video = nil;
// Creating a fetch request to check whether the video already exists, calling from the AppDelegate
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Video"];
request.predicate = [NSPredicate predicateWithFormat:@"language = %@", name];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"language" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *videoTitles = [context executeFetchRequest:request error:&error];
if (!videoTitles)
{
// Handle Error
}
else if (![videoTitles count])
{
// If the video count is 0 then create it
video = [NSEntityDescription insertNewObjectForEntityForName:@"Video" inManagedObjectContext:context];
video.language = name;
}
else
{
// If the object exists, just return it
video = [videoTitles lastObject];
}
return video;
}
所以在 Video
选项卡中,我使用 NSFetchedResultsController
是这样的:
- (NSFetchedResultsController *)fetchedResultsController
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Video" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
NSPredicate *d = [NSPredicate predicateWithFormat:@"language != nil"];
[fetchRequest setPredicate:d];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"language" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
而 cellForRow
是:
VideoTabTableViewCell *customCell = (VideoTabTableViewCell *)cell;
Video *video = [self.fetchedResultsController objectAtIndexPath:indexPath];
customCell.videoTabCellLabel.text = video.language;
customCell.videoTabCellLabel.textColor = [UIColor whiteColor];
这成功地引入了语言。
现在,出于测试目的,我希望“语言”选项卡执行完全相同的操作。我有一个 Language
实体的原因是因为语言选项卡将是具有视频和传单的语言的组合。
所以在 Languages
选项卡中,我的 fetchedResultsController
是:
- (NSFetchedResultsController *)fetchedResultsController
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Language" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
// NSPredicate *d = [NSPredicate predicateWithFormat:@"name != nil"];
// [fetchRequest setPredicate:d];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"videos.language" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
而 cellForRow
是:
VideoTabTableViewCell *customCell = (VideoTabTableViewCell *)cell;
Language *languages = [self.fetchedResultsController objectAtIndexPath:indexPath];
customCell.videoTabCellLabel.text = languages.videos.language;
customCell.videoTabCellLabel.textColor = [UIColor whiteColor];
更新
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
静态 NSString *CellIdentifier = @"langauges tab";
VideoTabTableViewCell *cell = (VideoTabTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.languagesTabTableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
// The boiler plate code for the NSFetchedResultsControllerDelegate
UITableView *tableView = self.languagesTabTableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
default:
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.languagesTabTableView endUpdates];
}
我正在从 viewDidLoad
调用 fetchedResultsController
并从 viewWillAppear
重新加载 table。
但是,Languages
选项卡上的情况是它只显示我最后添加的语言,每次启动时,我都会创建另一个新的空单元格。
我只是想不通这究竟是怎么回事。
澄清一下,这里的主要问题不是幻像单元格,而是为什么语言只选取最后一个条目而不选取其他条目。
任何指导将不胜感激。
我不熟悉托管对象,但这看起来就像一本字典。具有相同名称的多个 insertNewObjectForEntityForName 意味着最后一个将覆盖其余的。
Apple 文档似乎也表明了这一点:
Discussion
This method makes it easy for you to create instances of a given entity without worrying about the details of managed object creation. The method is conceptually similar to the following code example.
NSManagedObjectModel *managedObjectModel =
[[context persistentStoreCoordinator] managedObjectModel];
NSEntityDescription *entity =
[[managedObjectModel entitiesByName] objectForKey:entityName];
NSManagedObject *newObject = [[NSManagedObject alloc]
initWithEntity:entity insertIntoManagedObjectContext:context];
return newObject;
注意上面的objectForKey!与 NSDictionary
相同
============================================= ====================
dequeueReusableCellWithIdentifier 并不总是 return 非零对象。它用于重用现有单元格。但如果没有可用的,您需要 alloc/init 一个。
类似于:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
// populate your cell
return cell;
}
我认为您需要改进数据模型:
首先,从 Language
到 Video
的关系有一个复数名称,videos
,这表明您希望每个 Language
对象与许多 Video
对象。但是模型编辑器中的图像显示该关系当前定义为 "to-one".
其次,为什么有一个 Language
实体, 和 Video
实体的 language
属性?从您的代码来看, language
属性似乎是一个表示语言名称的字符串。我建议您应该在 Language
实体上设置一个 name
属性。
除此之外,问题的症结在于loadVideosTab
方法。它只创建一个 Language
对象:
Language *language = [NSEntityDescription insertNewObjectForEntityForName:@"Language" inManagedObjectContext:context];
然后创建(或获取)几个Video
对象,并与(一个)Language
建立关系,例如:
Video *chineseLanguage = (Video *)[Video videoLanguage:chinese inManagedObjectContext:context];
language.videos = chineseLanguage;
但是,因为 videos
关系是 "to-one",所以 Language
对象只能与一个 Video
相关。所以每次设置关系时,旧的都会被删除。在您的方法结束时,您的 Language
仅与泰米尔语 Video
对象相关。其他七个 Video
对象与任何 Language
.
无关
每个 运行 创建一个新的 Language
,并与泰米尔 Video
建立关系。因为每个 Video
只能有一个 Language
,当建立这种关系时,CoreData 会删除泰米尔语视频与 "old" Language
对象的关系。因此,您最终会得到几个与任何 Video
无关的 "old" Language
对象 - 这些是您的语言 table 视图中的空白行。
编辑
关于处理对多关系的注意事项:该关系表示为 NSSet。如果你正在设置一个关系(并想删除现有的关系),你可以使用:
language.videos = [NSSet setWithObject:tamilLanguage];
或者一次设置多个对象,使用:
language.videos = [NSSet setWithArray:@[chineseLanguage, dutchLanguage, tamilLanguage]];
这些会破坏现有关系,因此要添加关系,同时保持现有关系,请使用NSMutableSet
:
NSMutableSet *videos = [language mutableSetValueForKey:@"videos"];
[videos addObject:tamilLanguage];
(和 removeObject
类似,只删除一个相关对象)。我发现这些方法相当不直观,所以如果我有一个关系的逆函数是 "to-one",我会使用它:
tamilLanguage.videoLanguage = 语言;
话虽如此,我现在想知道这种反向关系是否也应该是 "to-many" - Video
可以有很多 Language
吗?
我有一个简单的应用程序,每个 UITabBar
中有一个 UITabBarController
和 2 个 UITableViewControllers
。第一个 UITableViewController
称为 Videos
,第二个称为 Languages
。
Videos
将仅代表有视频的语言,而语言将显示所有语言。
出于测试目的,我从 AppDelegate 填充核心数据实体。
我的核心数据模型如下:
填充核心数据的方法如下所示:
- (void)loadVideosTab
{
// Here is where we'll load up the Videos tab.
NSManagedObjectContext *context = [self managedObjectContext];
NSString *chinese = @"Chinese";
NSString *dutch = @"Dutch";
NSString *english = @"English";
NSString *french = @"French";
NSString *italian = @"Italian";
NSString *punjabi = @"Punjabi";
NSString *spanish = @"Spanish";
NSString *tamil = @"Tamil - தமிழ்";
Language *language = [NSEntityDescription insertNewObjectForEntityForName:@"Language" inManagedObjectContext:context];
Video *chineseLanguage = (Video *)[Video videoLanguage:chinese inManagedObjectContext:context];
language.videos = chineseLanguage;
Video *dutchLanguage = (Video *)[Video videoLanguage:dutch inManagedObjectContext:context];
language.videos = dutchLanguage;
Video *englishLanguage = (Video *)[Video videoLanguage:english inManagedObjectContext:context];
language.videos = englishLanguage;
Video *frenchLanguage = (Video *)[Video videoLanguage:french inManagedObjectContext:context];
language.videos = frenchLanguage;
Video *italianLanguage = (Video *)[Video videoLanguage:italian inManagedObjectContext:context];
language.videos = italianLanguage;
Video *punjabiLanguage = (Video *)[Video videoLanguage:punjabi inManagedObjectContext:context];
language.videos = punjabiLanguage;
Video *spanishLanguage = (Video *)[Video videoLanguage:spanish inManagedObjectContext:context];
language.videos = spanishLanguage;
Video *tamilLanguage = (Video *)[Video videoLanguage:tamil inManagedObjectContext:context];
language.videos = tamilLanguage;
NSError *error = nil;
if (![context save:&error])
{
// Error
}
}
我在 Video
实体上调用的类别是:
+ (Video *)videoLanguage:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context
{
Video *video = nil;
// Creating a fetch request to check whether the video already exists, calling from the AppDelegate
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Video"];
request.predicate = [NSPredicate predicateWithFormat:@"language = %@", name];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"language" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *videoTitles = [context executeFetchRequest:request error:&error];
if (!videoTitles)
{
// Handle Error
}
else if (![videoTitles count])
{
// If the video count is 0 then create it
video = [NSEntityDescription insertNewObjectForEntityForName:@"Video" inManagedObjectContext:context];
video.language = name;
}
else
{
// If the object exists, just return it
video = [videoTitles lastObject];
}
return video;
}
所以在 Video
选项卡中,我使用 NSFetchedResultsController
是这样的:
- (NSFetchedResultsController *)fetchedResultsController
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Video" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
NSPredicate *d = [NSPredicate predicateWithFormat:@"language != nil"];
[fetchRequest setPredicate:d];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"language" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
而 cellForRow
是:
VideoTabTableViewCell *customCell = (VideoTabTableViewCell *)cell;
Video *video = [self.fetchedResultsController objectAtIndexPath:indexPath];
customCell.videoTabCellLabel.text = video.language;
customCell.videoTabCellLabel.textColor = [UIColor whiteColor];
这成功地引入了语言。
现在,出于测试目的,我希望“语言”选项卡执行完全相同的操作。我有一个 Language
实体的原因是因为语言选项卡将是具有视频和传单的语言的组合。
所以在 Languages
选项卡中,我的 fetchedResultsController
是:
- (NSFetchedResultsController *)fetchedResultsController
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Language" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
// NSPredicate *d = [NSPredicate predicateWithFormat:@"name != nil"];
// [fetchRequest setPredicate:d];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"videos.language" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
而 cellForRow
是:
VideoTabTableViewCell *customCell = (VideoTabTableViewCell *)cell;
Language *languages = [self.fetchedResultsController objectAtIndexPath:indexPath];
customCell.videoTabCellLabel.text = languages.videos.language;
customCell.videoTabCellLabel.textColor = [UIColor whiteColor];
更新 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 静态 NSString *CellIdentifier = @"langauges tab";
VideoTabTableViewCell *cell = (VideoTabTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.languagesTabTableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
// The boiler plate code for the NSFetchedResultsControllerDelegate
UITableView *tableView = self.languagesTabTableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
default:
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.languagesTabTableView endUpdates];
}
我正在从 viewDidLoad
调用 fetchedResultsController
并从 viewWillAppear
重新加载 table。
但是,Languages
选项卡上的情况是它只显示我最后添加的语言,每次启动时,我都会创建另一个新的空单元格。
我只是想不通这究竟是怎么回事。
澄清一下,这里的主要问题不是幻像单元格,而是为什么语言只选取最后一个条目而不选取其他条目。
任何指导将不胜感激。
我不熟悉托管对象,但这看起来就像一本字典。具有相同名称的多个 insertNewObjectForEntityForName 意味着最后一个将覆盖其余的。
Apple 文档似乎也表明了这一点:
Discussion
This method makes it easy for you to create instances of a given entity without worrying about the details of managed object creation. The method is conceptually similar to the following code example.
NSManagedObjectModel *managedObjectModel =
[[context persistentStoreCoordinator] managedObjectModel];
NSEntityDescription *entity =
[[managedObjectModel entitiesByName] objectForKey:entityName];
NSManagedObject *newObject = [[NSManagedObject alloc]
initWithEntity:entity insertIntoManagedObjectContext:context];
return newObject;
注意上面的objectForKey!与 NSDictionary
相同============================================= ====================
dequeueReusableCellWithIdentifier 并不总是 return 非零对象。它用于重用现有单元格。但如果没有可用的,您需要 alloc/init 一个。
类似于:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
// populate your cell
return cell;
}
我认为您需要改进数据模型:
首先,从 Language
到 Video
的关系有一个复数名称,videos
,这表明您希望每个 Language
对象与许多 Video
对象。但是模型编辑器中的图像显示该关系当前定义为 "to-one".
其次,为什么有一个 Language
实体, 和 Video
实体的 language
属性?从您的代码来看, language
属性似乎是一个表示语言名称的字符串。我建议您应该在 Language
实体上设置一个 name
属性。
除此之外,问题的症结在于loadVideosTab
方法。它只创建一个 Language
对象:
Language *language = [NSEntityDescription insertNewObjectForEntityForName:@"Language" inManagedObjectContext:context];
然后创建(或获取)几个Video
对象,并与(一个)Language
建立关系,例如:
Video *chineseLanguage = (Video *)[Video videoLanguage:chinese inManagedObjectContext:context];
language.videos = chineseLanguage;
但是,因为 videos
关系是 "to-one",所以 Language
对象只能与一个 Video
相关。所以每次设置关系时,旧的都会被删除。在您的方法结束时,您的 Language
仅与泰米尔语 Video
对象相关。其他七个 Video
对象与任何 Language
.
每个 运行 创建一个新的 Language
,并与泰米尔 Video
建立关系。因为每个 Video
只能有一个 Language
,当建立这种关系时,CoreData 会删除泰米尔语视频与 "old" Language
对象的关系。因此,您最终会得到几个与任何 Video
无关的 "old" Language
对象 - 这些是您的语言 table 视图中的空白行。
编辑
关于处理对多关系的注意事项:该关系表示为 NSSet。如果你正在设置一个关系(并想删除现有的关系),你可以使用:
language.videos = [NSSet setWithObject:tamilLanguage];
或者一次设置多个对象,使用:
language.videos = [NSSet setWithArray:@[chineseLanguage, dutchLanguage, tamilLanguage]];
这些会破坏现有关系,因此要添加关系,同时保持现有关系,请使用NSMutableSet
:
NSMutableSet *videos = [language mutableSetValueForKey:@"videos"];
[videos addObject:tamilLanguage];
(和 removeObject
类似,只删除一个相关对象)。我发现这些方法相当不直观,所以如果我有一个关系的逆函数是 "to-one",我会使用它:
tamilLanguage.videoLanguage = 语言;
话虽如此,我现在想知道这种反向关系是否也应该是 "to-many" - Video
可以有很多 Language
吗?