Populating TableView with NSMutableSet - objective-c

I am using core data and trying to populate a UITableView with an NSMutableSet. I have two entities, Teams and Players. On my addTeamsController I am saving a player to the team as follows
-(void)saveButtonWasPressed {
self.team =[NSEntityDescription insertNewObjectForEntityForName:#"Team" inManagedObjectContext:self.managedObjectContext];
Player *newPlayer = (Player *)[NSEntityDescription insertNewObjectForEntityForName:#"Player"
inManagedObjectContext:self.managedObjectContext];
team.schoolName = _schoolName.text;
team.teamName = _teamName.text;
team.teamID = _teamName.text;
team.season = _season.text;
team.headCoach = _headCoach.text;
team.astCoach = _assistantCoach.text;
[self.team addPlayers:_tempSet];
[self.managedObjectContext save:nil];
[self.navigationController popViewControllerAnimated:YES];
}
On another viewController I am trying to populate a tableview with that teams players. To do that I am doing as follows
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"firstName" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
_array = [[_team.players allObjects] sortedArrayUsingDescriptors:sortDescriptors];
and then on my cell for row and index path I am doing the following
cell.textLabel.text = [_array objectAtIndex:indexPath.row];
And I get the error
[Player isEqualToString:]: unrecognized selector sent to instance
I am wondering what the best approach to filling the tableview sorted by the players first names is.

The best way to populate a table from a core data store is to use an NSFetchedResultController. But that is not going to fix the problem you're having, the problem is that your trying to set cell.textLabel.text to an NSManagedObject, which doesn't work. You can set
cell.textLabel.text = Player.someStringAttribute

Related

NSFetchResultsController sorting is not working when inserting new entity

I have an CoreData entity called "MyPhoto" with the attributes :- photoData, timeStamp, folderName. Setting the today Date with Time to timeStamp property when saving photoData to core data. I want sections with folderName and inside the section I want to sort the photos with timeStamp. I am using and NSFetchResultsController to fetch the data & UICollectionView to display it.
Problem is: When I try to insert the new photo, it is not inserting in the correct sorting order but when I relaunch the app, it will show the all the photos in a correct sorting order.
here is the code I am using:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *moc = [[CoreDataManager sharedInstance] managedObjectContext];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MyPhoto" inManagedObjectContext:moc];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Sort using the timeStamp property.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"folderName" ascending:YES];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"timeStamp" ascending:NO];
[fetchRequest setSortDescriptors:#[sortDescriptor, sortDescriptor1]];
// Use the folderName property to group into sections.
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc sectionNameKeyPath:#"folderName" cacheName:#"Root"];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
I hope I have explained my problem clearly. Thanks in advance for your help.
I see you are setting the delegate. Have you actually implemented any of the delegate methods?
For starters, you could just call reloadData in controllerDidChangeContent:

How to sort NSMutableArray key by date (Facebook Birthdays?)

Im trying to use NSSortDescriptor to sort the NSMutableArray *friends, key:birthday, by date, I'm getting null for all the birthdays in my NSLog, however the names are still logging. If I pull out my NSSortDescriptor my NSLog will give me the values again, wondering why i lose the values in passing them through the NSSortDescriptor, and how I can pull this off. Im using the Hackbook sample code to learn Facebook integration, and have modified the code to give me my friends birthdays, and id like to have them sorted January - December in format 1/1 - 12/31 Is it because of the randomizing pull of resultData of a friends list? Thanks you in advance, ill be sure to accept as soon as we get to the bottom of this!
******************************CODE TO PULL KEYS BIRTHDAY AND NAMES FROM GRAPH API ******
- (void)getUserFriends {
currentAPICall = kAPIGraphUserFriends;
HackbookAppDelegate *delegate = (HackbookAppDelegate *)[[UIApplication sharedApplication] delegate];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"name, birthday", #"fields", nil];
[[delegate facebook] requestWithGraphPath:#"me/friends" andParams:params andDelegate:self];
[self apiGraphFriends];
}
***********RANDOMIZE LIST OF FRIENDS NAMES W BIRTHDAYS AND PUSH TO VIEW CONTROLLER
NSMutableArray *friends = [[NSMutableArray alloc] initWithCapacity:1];
NSArray *resultData = [result objectForKey:#"data"];
if ([resultData count] > 0) {
for (NSUInteger i=0; i<[resultData count] && i < 1000; i++) {
[friends addObject:[resultData objectAtIndex:i]];
}
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"birthday"
ascending:TRUE];
[friends sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
// LOG VALUES OF KEYS birthday and name FOR DEBUGGING
NSLog(#"name %#" , [friends valueForKey:#"name"]);
NSLog(#"birthday %#" , [friends valueForKey:#"birthday"]);
// Show the friend information in a new view controller
NSLog(#"Check#3");
APIResultsViewController *controller = [[APIResultsViewController alloc]
initWithTitle:#"Friends Birthdays"
data:friends action:#""];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
} else {
[self showMessage:#"You have no friends."];
}
[friends release];
8/10 edit added code above that shows how i am getting these names and birthdays, i believe them both to be NSStrings per http://developers.facebook.com/docs/reference/api/user/ Just scroll down to the birthday part. I want to also mention, VERY IMPORTANT, that i have extended permissions, and this is not a permission issue, its something im doing wrong when i try to sort the array, and i believe my inexperience is my own worst enemy here. Thanks!
This may help you identify the problem. In general, this allows you to sort a list with a custom comparator, but it may be useful to determine why sortUsingDescriptors is nulling your birthdays. Perhaps one or more of your birthdays is not valid.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:#"birthday"
ascending:YES
comparator:^NSComparisonResult(id obj1, id obj2) {
NSLog(#"bday1 = '%#' bday2 = '%#'", obj1, obj2);
return NSOrderedSame;
}];

Add empty section to NSFetchedResultsController

I am making a view just like the iPhone Calendar ListView. I am using core data and getting appointments and grouping them by date.
However just like in the iPhone listview I need to add a blank section for today even if there are no appointments. I cannot figure out how to do this for a section with no appointments since I am doing the sorting before I create the grouping.
How would I add an empty section to the NSFetchedResultsController and have it resorted so that today's date is in the correct spot and not at the end of the list?
- (NSFetchedResultsController *)fetchedResultsController {
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Appointments" inManagedObjectContext:[[CoreDataHelper sharedInstance] managedObjectContext]];
[fetchRequest setEntity:entity];
//[fetchRequest setIncludesPendingChanges:YES];
// Set the batch size to a suitable number.
//[fetchRequest setFetchBatchSize:20];
// Sort using the date / then time property.
NSSortDescriptor *sortDescriptorDate = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSSortDescriptor *sortDescriptorTime = [[NSSortDescriptor alloc] initWithKey:#"start_time" ascending:YES selector:#selector(localizedStandardCompare:)];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptorDate, sortDescriptorTime, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Use the sectionIdentifier property to group into sections.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[[CoreDataHelper sharedInstance] managedObjectContext] sectionNameKeyPath:#"date" cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
return fetchedResultsController;
}
You can't have empty sections with NSFetchedResultsController - that's just the way it is designed at the moment, and I would call it a limitation :)
This problem has been encountered and addressed by a Timothy Armes who has created a class TAFetchedResultsController, which allows for empty sections. It's a replacement for NSFetchedResultsController. It also allows you to sort your sections on fields which aren't the section name (quite handy)
However, you will need to make changes to your Core Data model - it's not quite a drop in replacement.
https://github.com/timothyarmes/TAFetchedResultsController
But it does work well, and will solve your problem if you are willing to re-do your data model.
Hope this helps :)

Core Data Edit/Save Attributes in an Entity

I am struggling with the editing/saving in Core Data and need some help in this. I am using NSFetchedResultsController and have an entity named Golfer with attributes- first_name, last_name, email_id and others in Core Data. So, I know how to add and remove golfers from the database.
I am working on one view controller called ViewManager (kinda base view for all my classes) and it has 2-3 Custom UIViews inside it. I animate them in and out whenever I need them.
I add a golfer to the tableview, then on didSelectRow tableview method, I present my edit View inside the same ViewManager controller and try to update the textfields in the edit view using the following code, but it's updating at random indexes in the tableview and not working for me. Any help would be greatly appreciated.
- (IBAction)saveEditGolfersView:(id)sender
{
AppDelegate * applicationDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
NSManagedObjectContext * context = [applicationDelegate managedObjectContext];
// Retrieve the entity from the local store -- much like a table in a database
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Golfer" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
// Set the sorting -- mandatory, even if you're fetching a single record/object
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"first_name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1,nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release]; sortDescriptors = nil;
[sortDescriptor1 release]; sortDescriptor1 = nil;
NSError * error;
NSArray * objects = [context executeFetchRequest:request error:&error];
for(int i = 0; i<[objects count]; i++)
{
Golfer * golfguy = [objects objectAtIndex:i];
golfguy.first_name = mEditFirstName.text;
golfguy.middle_name = mEditMiddleName.text;
golfguy.last_name = mEditLastName.text;
golfguy.email_id = mEditEmailField.text;
golfguy.contactNumber = mEditContactNum.text;
golfguy.picture = mEditPictureView.image;
NSLog(#"name-%#", golfguy.first_name);
}
[request release]; request = nil;
error = nil;
[context save:&error];
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut
animations:^ {
mEditGolfersView.frame = CGRectMake(-480, mEditGolfersView.frame.origin.y, mEditGolfersView.frame.size.width, mEditGolfersView.frame.size.height);
}
completion:^(BOOL finished) {
mEditGolfersView.hidden = YES;
}];
}
If I have read this code correct, then a call to -(IBAction)saveEditGolfersView:(id)sender will set all the Golfers with the exact properties, which I expect is not what you want.
I am not quite sure what the problem is, but I hypothesize that you need an NSPredicate to go along with your NSFetchRequest in order to change the correct Golfer(s).
Maybe I missed something, but this code says to me "hey, I'm going to load all of the Golfer in the database, order them by their first name, and then set all of their properties to the exact same text fields on this page". Just sounds like bad news...
To edit just one golfer, be sure to store the golfer you are editing in a property some where. Since you keep the managedObjectContext stored on the applicationDelegate, it will stay alive and thus keep your core data objects alive. That would avoid the expensive fetch that you are doing in the save view. If, however, you do not want to keep a reference to the golfer object, each NSManagedObject has an objectId, which is the identifier used by core data. You could use the objectId in a fetch predicate like so:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"objectId == %#", self.editingGolferObjectId];
[request setPredicate:predicate];
I would choose to keep reference to the object in your case, rather than the objectId

Core data one-to-many relationship and Table view

Well, I have been beating my head over this one for some time now, definitely over a week and I just don't know where I am going wrong. Your help would be greatly appreciated!!
Here is the app idea. I have two entities modeled in core data. The Tycoon entity has a one to many relationship with Speech, so each Tycoon is capable of having more than one speech.
In the Tycoon entity, the relationship is titled 'TycoonToSpeech' and in the Speech entity, the relationship to Tycoon is titled 'SpeechToTycoon' (this is not a one to many relationship).
Problem 1: I thought I had created my relationships in the appdelegate.m file correctly, but I am not sure. Here is the code in my appdelegate to generate content. Should I do anything more with the 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];
Problem 2: The main and really annoying problem, I don't know how to make didSelectRowAtIndexPath in my root view controller work so that when I click on 'Steve Jobs' in the table view, it brings up only his speeches and when I click on Warren Buffet it only brings up his speeches. I have banged my head against the wall trying to get this right. At the moment, when I click on either Steve Jobs or Warren Buffet it takes me to a new table view showing 'Steve Jobs' and 'Warren Buffet', so basically the exact same table view as the original!!! Here is my code for 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];
Newly Edited here**
OK, here is the main code in my SpeechViewController.m file. The numberOfRowsInSection method seems to be working, but the real problem is the cellForRowAtIndexPath that is the problem. I know I am probably doing something very stupid, but I don't know what it is.
- (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;
}
New speech view controller to language points view controller
I added this in the app delegate to add objects to my language points entity.
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"];
Then in my speechViewController.m file I created an NSArray called speechInfo, then here is my didSelectRowAtIndexPath method.
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];
I think this is where things are going wrong, I don't think I am getting the object here correctly because I do an NSLog on speech.Name in the LangPointsViewController and it comes up null, where as if I do an NSLog for tycoon.Name in the SpeechViewController it prints the person's name I clicked on. Is it the NSArray that's incorrect.
Problem #1
First your relationship names are bad. They should start with a lower case and they should simply describe what is on the other side of the relationship. You already know where you are. So name them tycoon and speeches respectively. Second, because relationships are bi-directional you can construct your data easier, see the following:
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"];
Note that I am setting the relationship from the Speech side. Core Data will handle the other side.
Problem #2
Without looking at your entire root view controller it is hard to say what you are doing "wrong". However, I would not re-use a view controller to display two different types of objects. That is bad form and leads to code cruft.
Instead I would create a second "master" view controller that is designed to handle speeches. Then you can just pass in the tycoon and your SpeechViewController can run just off an array derived from the relationship or it can build up its fetched results controller internally. Even of greater value is the ability to customize its cells, title, etc. to fit the data it is displaying.
Problem #3
First a comment about the new code you added:
SpeechViewController *speechView = [[SpeechViewController alloc] initWithNibName:#"SpeechViewController" bundle:[NSBundle mainBundle]];
Tycoon *tycoons = (Tycoon *)[fetchedResultsController objectAtIndexPath:indexPath];
speechView.tycoons = tycoons;
[self.navigationController pushViewController:speechView animated:YES];
There is ZERO reason to cast out of a -[NSFetchedResultsController objectAtIndexPath:]. Any method that returns id can be assigned to any pointer.
Casting is a lie to the compiler and should be avoided at all cost.
Now, leaving that aside, your code is fine. I would name the property 'tycoon' instead of 'tycoons' because you are passing in a single Tycoon entity.
On the SpeechViewController side you can now access the speeches associated with that Tycoon entity and display them however you choose.
What is the issue you are seeing?
Problem #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;
}
Ok starting at the top. First, a relationship will return a NSSet not a NSArray. The results from a relationship are unordered. Therefore we grab the results as a NSSet and then sort them. I guessed that there is a name attribute on your Speech entity.
Once we have them sorted we can grab the item at the row. This will return a Speech entity. I assigned it to id because we are going to be using KVC anyway.
Finally, I use KVC to get the name attribute from the Speech entity and assign it to the textLabel of the cell.
As for your -tableView: numberOfRowsInSection:, that one is far simpler:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[self tycoon] valueForKey:#"TycoonToSpeech"] count];
}
Because you only have one section you only need to return the count of speeches.
I mentioned before that your attribute names need some work. Since Tycoon is just an object and TycoonToSpeech is just a property on that object, the property should really be called speeches because it is no more special than any other property on an object. The attribute name flows better in your code and makes your code easier to consume. In addition, Objective-C naming conventions call for attributes aka properties to start with a lower case.