Задача # 1
Сначала ваши отношения плохие.Они должны начинаться со строчной буквы, и они должны просто описать то, что находится на другой стороне отношений.Вы уже знаете, где вы находитесь.Назовите их 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
.Базовые данные будут обрабатывать другую сторону.
Задача № 2
Не глядя на весь контроллер корневого представления, трудно сказать, что вы делаете «неправильно».Однако я бы не стал повторно использовать контроллер представления для отображения двух разных типов объектов.Это плохая форма и ведет к краже кода.
Вместо этого я бы создал второй «главный» контроллер вида, предназначенный для обработки речей.Затем вы можете просто передать магната, и ваш SpeechViewController может запустить только из массива, полученного из отношений, или он может создать свой извлеченный контроллер результатов изнутри.Еще большее значение имеет возможность настраивать свои ячейки, заголовок и т. Д. В соответствии с отображаемыми данными.
Задача № 3
Сначала добавьте комментарий о новом коде, который вы добавили:
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
, может быть назначен любому указателю.
Приведение является ложью для компилятора, и его следует избегать любой ценой.
Теперь, оставив это в стороне, ваш код в порядке.Я бы назвал свойство «магнат» вместо «магнат», потому что вы передаете одну сущность магната.
На стороне SpeechViewController
теперь вы можете получить доступ к речам, связанным с этой сущностью магната, и вывести их на экран, однакоВы выбираете.
В чем проблема, которую вы видите?
Задача # 4
- (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
сущности есть атрибут name.
Как только мы их отсортируем, мы сможем взять элемент в строке.Это вернет 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 атрибуты, называемые свойствами, должны начинаться со строчной буквы.