好吧,我已经在这个问题上打了一段时间了,现在已经过了一个星期,我只是不知道自己哪里出错了。非常感谢您的帮助!!
这是应用程序的想法。我有两个以核心数据为模型的实体。大亨实体与Speech有一对多的关系,因此每个大亨都能够有多个演讲。 在Tycoon实体中,这种关系的标题是“TycoonToSpeech”,而在言语实体中,与Tycoon的关系名为'SpeechToTycoon'(这不是一对多关系)。
问题1:我认为我已经在appdelegate.m文件中正确创建了我的关系,但我不确定。以下是我的appdelegate中用于生成内容的代码。我应该用NSMutableSets做什么吗???
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *tycoonEntity = [NSEntityDescription entityForName:@"Tycoon" inManagedObjectContext:context];
NSManagedObject *steve = [NSEntityDescription insertNewObjectForEntityForName:[tycoonEntity name] inManagedObjectContext:context];
[steve setValue:@"Steve Jobs" forKey:@"Name"];
int orgId = [steve hash];
[steve setValue:[NSNumber numberWithInt:orgId] forKey:@"Id"];
NSManagedObject *warren = [NSEntityDescription insertNewObjectForEntityForName:[tycoonEntity name] inManagedObjectContext:context];
[warren setValue:@"Warren Buffet" forKey:@"Name"];
int orgId2 = [warren hash];
[warren setValue:[NSNumber numberWithInt:orgId2] forKey:@"Id"];
NSEntityDescription *speechEntity = [NSEntityDescription entityForName:@"Speech" inManagedObjectContext:context];
NSManagedObject *stanford = [NSEntityDescription insertNewObjectForEntityForName:[speechEntity name] inManagedObjectContext:context];
[stanford setValue:[NSNumber numberWithInt:[stanford hash]] forKey:@"speechId"];
[stanford setValue:@"Stanford" forKey:@"speechName"];
NSManagedObject *wwdc = [NSEntityDescription insertNewObjectForEntityForName:[speechEntity name] inManagedObjectContext:context];
[wwdc setValue:[NSNumber numberWithInt:[wwdc hash]] forKey:@"speechId"];
[wwdc setValue:@"WWDC" forKey:@"speechName"];
NSManagedObject *shareHolder = [NSEntityDescription insertNewObjectForEntityForName:[speechEntity name] inManagedObjectContext:context];
[shareHolder setValue:[NSNumber numberWithInt:[shareHolder hash]] forKey:@"speechId"];
[shareHolder setValue:@"Shareholder's Meeting" forKey:@"speechName"];
NSManagedObject *columbia = [NSEntityDescription insertNewObjectForEntityForName:[speechEntity name] inManagedObjectContext:context];
[columbia setValue:[NSNumber numberWithInt:[columbia hash]] forKey:@"speechId"];
[columbia setValue:@"Columbia" forKey:@"speechName"];
NSMutableSet *jobsSpeeches = [steve mutableSetValueForKey:@"TycoonToSpeech"];
[jobsSpeeches addObject:stanford];
[jobsSpeeches addObject:wwdc];
NSMutableSet *warrenSpeeches = [warren mutableSetValueForKey:@"TycoonToSpeech"];
[warrenSpeeches addObject:shareHolder];
[warrenSpeeches addObject:columbia];
问题2:主要且非常烦人的问题,我不知道如何在我的根视图控制器中使用didSelectRowAtIndexPath工作,这样当我在表格视图中点击“史蒂夫·乔布斯”时,它只会显示他的演讲和当我点击Warren Buffet时,它只会提出他的演讲。为了做到这一点,我把头撞在了墙上。目前,当我点击史蒂夫乔布斯或沃伦巴菲特时,它会带我到一个新的桌面视图,显示'史蒂夫乔布斯'和'沃伦巴菲特',所以基本上与原始的表视图完全相同!这是我的didSelectRowAtIndexPath代码。
// Create a new table view of this very same class.
RootViewController *rootViewController = [[RootViewController alloc]
initWithStyle:UITableViewStylePlain];
// Pass the managed object context
rootViewController.context = self.context;
NSPredicate *predicate = nil;
// Get the object the user selected from the array
NSManagedObject *selectedObject = [entityArray objectAtIndex:indexPath.row];
rootViewController.entityName = @"Speeches";
// Create a query predicate to find all child objects of the selected object.
predicate = [NSPredicate predicateWithFormat:@"SpeechToTycoon == %@", selectedObject];
[rootViewController setEntitySearchPredicate:predicate];
//Push the new table view on the stack
[self.navigationController pushViewController:rootViewController animated:YES];
[rootViewController release];
此处新编辑* *
好的,这是我的SpeechViewController.m文件中的主要代码。 numberOfRowsInSection方法似乎正在工作,但真正的问题是cellForRowAtIndexPath是问题所在。我知道我可能做了一些非常愚蠢的事情,但我不知道它是什么。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSArray *speeches = (NSArray *)tycoon.TycoonToSpeech;
// Configure the cell...
cell.textLabel.text = [[speeches objectAtIndex:indexPath.row] retain];
return cell;
}
新语音视图控制器到语言点视图控制器
我在app委托中添加了这个,以便将对象添加到我的语言点实体。
NSEntityDescription *langPointEntity = [NSEntityDescription entityForName:@"LanguagePoints" inManagedObjectContext:context];
NSManagedObject *pointOne = [NSEntityDescription insertNewObjectForEntityForName:[langPointEntity name] inManagedObjectContext:context];
[pointOne setValue:[NSNumber numberWithInt:[pointOne hash]] forKey:@"LangId"];
[pointOne setValue:@"Drop out" forKey:@"LangPoint"];
[pointOne setValue:stanford forKey:@"LanguagePointsToSpeech"];
然后在我的speechViewController.m文件中创建了一个名为speechInfo的NSArray,然后这是我的didSelectRowAtIndexPath方法。
LangPointsViewController *langPointsView = [[LangPointsViewController alloc] initWithNibName:@"LangPointsViewController" bundle:[NSBundle mainBundle]];
Speech *speech = [speechInfo objectAtIndex:indexPath.row];
langPointsView.speech = speech;
[self.navigationController pushViewController:langPointsView animated:YES];
[langPointsView release];
我认为这是出错的地方,我不认为我在这里正确获取对象,因为我在LangPointsViewController中对speech.Name执行了一个NSLog,它出现了null,就好像我做了一个NSLog对于SpeechViewController中的tycoon.Name,它会打印我点击的人名。 NSArray是不正确的吗?
答案 0 :(得分:9)
首先你的关系名称不好。它们应该以小写字母开头,它们应该简单地描述关系另一方面的内容。你已经知道你在哪里。因此,请分别命名tycoon
和speeches
。其次,由于关系是双向的,您可以更轻松地构建数据,请参阅以下内容:
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *steve = [NSEntityDescription insertNewObjectForEntityForName:@"Tycoon" inManagedObjectContext:context];
[steve setValue:@"Steve Jobs" forKey:@"Name"];
int orgId = [steve hash];
[steve setValue:[NSNumber numberWithInt:orgId] forKey:@"Id"];
NSManagedObject *warren = [NSEntityDescription insertNewObjectForEntityForName:[tycoonEntity name] inManagedObjectContext:context];
[warren setValue:@"Warren Buffet" forKey:@"Name"];
int orgId2 = [warren hash];
[warren setValue:[NSNumber numberWithInt:orgId2] forKey:@"Id"];
NSManagedObject *stanford = [NSEntityDescription insertNewObjectForEntityForName:@"Speech" inManagedObjectContext:context];
[stanford setValue:[NSNumber numberWithInt:[stanford hash]] forKey:@"speechId"];
[stanford setValue:@"Stanford" forKey:@"speechName"];
[stanford setValue:warren forKey:@"tycoon"];
NSManagedObject *wwdc = [NSEntityDescription insertNewObjectForEntityForName:[speechEntity name] inManagedObjectContext:context];
[wwdc setValue:[NSNumber numberWithInt:[wwdc hash]] forKey:@"speechId"];
[wwdc setValue:@"WWDC" forKey:@"speechName"];
[wwdc setValue:warren forKey:@"tycoon"];
NSManagedObject *shareHolder = [NSEntityDescription insertNewObjectForEntityForName:[speechEntity name] inManagedObjectContext:context];
[shareHolder setValue:[NSNumber numberWithInt:[shareHolder hash]] forKey:@"speechId"];
[shareHolder setValue:@"Shareholder's Meeting" forKey:@"speechName"];
[shareHolder setValue:warren forKey:@"tycoon"];
NSManagedObject *columbia = [NSEntityDescription insertNewObjectForEntityForName:[speechEntity name] inManagedObjectContext:context];
[columbia setValue:[NSNumber numberWithInt:[columbia hash]] forKey:@"speechId"];
[columbia setValue:@"Columbia" forKey:@"speechName"];
[columbia setValue:warren forKey:@"tycoon"];
请注意,我正在设置Speech
方面的关系。核心数据将处理另一方。
如果不查看整个根视图控制器,很难说你做错了什么。但是,我不会重复使用视图控制器来显示两种不同类型的对象。这是糟糕的形式,导致代码残骸。
相反,我会创建第二个“主”视图控制器,旨在处理语音。然后你可以传入大亨,你的SpeechViewController可以运行从关系派生的数组,或者它可以在内部构建其获取的结果控制器。即使更有价值的是能够自定义其单元格,标题等以适合它正在显示的数据。
首先评论您添加的新代码:
SpeechViewController *speechView = [[SpeechViewController alloc] initWithNibName:@"SpeechViewController" bundle:[NSBundle mainBundle]];
Tycoon *tycoons = (Tycoon *)[fetchedResultsController objectAtIndexPath:indexPath];
speechView.tycoons = tycoons;
[self.navigationController pushViewController:speechView animated:YES];
ZERO 有理由退出-[NSFetchedResultsController objectAtIndexPath:]
。任何返回id
的方法都可以分配给任何指针。
Casting是编译器的谎言,应该不惜一切代价避免。
现在,把它放在一边,你的代码很好。我会将该物业命名为“大亨”而不是“大亨”,因为你传递了一个大亨实体。
在SpeechViewController
方面,您现在可以访问与该Tycoon实体相关联的演讲,并根据您的选择显示它们。
您看到的问题是什么?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSSet *speechesSet = [[self tycoon] valueForKey:@"TycoonToSpeech"];
// Sort the speeches
NSSortDescriptor *nameSort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortedSpeeches = [speechesSet sortedArrayUsingDescriptors:[NSArray arrayWithObject:nameSort]];
// Configure the cell...
id speech = [sortedSpeeches objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[speech valueForKey:@"name"]];
return cell;
}
好的从顶部开始。首先,关系将返回NSSet
而不是NSArray
。关系的结果是无序的。因此,我们将结果作为NSSet
抓取,然后对它们进行排序。我猜测你的Speech
实体上有一个名称属性。
一旦我们对它们进行了排序,我们就可以抓住该行的项目。这将返回Speech
实体。我将其分配给id
,因为无论如何我们将使用KVC。
最后,我使用KVC从name
实体获取Speech
属性,并将其分配给单元格的textLabel
。
至于你的-tableView: numberOfRowsInSection:
,那个更简单:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[self tycoon] valueForKey:@"TycoonToSpeech"] count];
}
因为您只有一个部分,所以您只需要返回演讲次数。
我之前提到过你的属性名称需要一些工作。由于Tycoon
只是一个对象而TycoonToSpeech
只是该对象的一个属性,因此该属性应该被称为speeches
,因为它不比对象上的任何其他属性更特殊。属性名称在代码中流动得更好,使代码更容易使用。此外,Objective-C命名约定要求属性aka属性以小写字母开头。