UITableView section and index by core data - ios

i use below code to binding tableview cell by "contacts" entity
- (NSManagedObjectContext *)managedObjectContext
{
NSManagedObjectContext *context=nil;
id delegate=[[UIApplication sharedApplication]delegate];
if ([delegate performSelector:#selector(managedObjectContext)])
{
context=[delegate managedObjectContext];
}
return context;
}
- (void)viewDidAppear:(BOOL)animated
{
//fetching contact into tableview
NSManagedObjectContext *moc=[self managedObjectContext];
totalFetch=[[NSFetchRequest alloc]initWithEntityName:#"Contacts"];
// 4 - Sort it if you want
totalFetch.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)]];
_contacts=[[moc executeFetchRequest:totalFetch error:nil]mutableCopy];
[self.myTable reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//create and initializetion cell
static NSString *cellIdentifier=#"cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
NSManagedObject *contact=[_contacts objectAtIndex:indexPath.row];
//implementing tableViewCells with Contact attribs
[cell.textLabel setText:[NSString stringWithFormat:#"%#",[contact valueForKey:#"name"]]];
[cell.detailTextLabel setText:[contact valueForKey:#"phoneNum"]];
UIImage *image = [UIImage imageWithData:[contact valueForKey:#"photo"]];
[cell.imageView setImage:image];
return cell;
}
now i want to add index and section to mytableview by first letter of "name" field in "contacts" entity, Please put your answers according to my code, thanks

You need to implement the following datasource methods for UITableView:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
The first two are standard and implement the cells that are going to be displayed in the table view.
The third one is the number of sections the table view should be divided up into. For something like this I would use an 'alphabet array' i.e. an array with all the letters of the alphabet in e.g.:
NSMutableArray *alphabetArray = [[NSMutableArray alloc] init];
for (int i = 0; i < 26; i++) {
char letter = 'A';
letter += i;
[alphabetArray addObject:[NSString stringWithFormat:#"%c", letter]];
}
You can return alphabetArray.count for the third datasource method.
The fourth method requests the section number for the section title, all you need to do here is return: [alphabetArray indexOfObject:title];.
The fifth method is asking for the title for a specific section so you can return: alphabetArray[section]; here.
Finally the sixth method is asking for all the titles in an array so you can just return alphabetArray here .
In order to get the number of rows in a section you need to break down your contacts array by starting letter. To do this you can use predicates e.g.
NSString *letter = alphabetArray[indexPath.section];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"name BEGINSWITH[cd] %#", letter]];
return filteredContacts.count;
You can apply the same logic to get the contact to display in a cell:
NSString *letter = alphabetArray[indexPath.section];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"name BEGINSWITH[cd] %#", letter]];
Contact *contact = filteredContacts[indexPath.row];
Hope this helps.

Related

Changed my code from previous. How to link tableview cells to specfic blog posts?

I've hardcoded all of the titles of my cells, and am looking to link each individual cell to a different blog post. The section titles are my keys, and the values are an array of the information pertaining to the title. How would I go about this? I'm a bit confused because due to the fact I have sections, the row selected number restarts as I begin the next section. There's some code involving a search bar so disregard that. An example would be so helpful!
#interface InfoTableViewController () {
NSDictionary *names;
NSArray *sectionTitles;
}
#end
#implementation InfoTableViewController {
NSArray *items;
NSArray *searchResults;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
names = #{#"Green Manual" : #[#"Basic Rules", #"Pledge Mom Interview", #"Pledge Class Song", #"Code of Conduct", #"History of XXX", #"Founding Sisters of XX", #"Inter-Chapter Council", #"General Facts", #"Crest of XXX", #"Sister of Mine", #"Greek Alphabet", #"Delta Chapter History",#"Actives", #"Associates, Recessives, Retired Actives, Inactives", #"Alumnae", #"Family Tree"],
#"Interviews" : #[#"Alyson Au", #"Jazzmin Boo", #"Shuki Chan", #"Ivy Cheng", #"Julie Ha", #"Jenny Hong", #"Linde Huang", #"Erica Jon", #"Jenny Lau", #"Jean Lin", #"Vivian Lo", #"Jackie Nguyen", #"Nhi Nguyen", #"Sarah Pham", #"Jasmine Ta", #"Diane Tran", #"Joyce Wong", #"Kathie Wong", #"Jennifer Xu"]};
sectionTitles = [[names allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [sectionTitles count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *sectionTitle = [sectionTitles objectAtIndex:section];
NSArray *sectionNames = [names objectForKey:sectionTitle];
return [sectionNames count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [sectionTitles objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath*)indexPath
{
//static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSString *sectionTitle = [sectionTitles objectAtIndex:indexPath.section];
NSArray *sectionNames = [names objectForKey:sectionTitle];
NSString *name = [sectionNames objectAtIndex:indexPath.row];
cell.textLabel.text = name;
NSLog(#"Row selected: %d", indexPath.row);
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name BEGINSWITH[cd] %#", searchText];
searchResults = [items filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
I assume you are trying to select a cell and detect that in order to move to a different controller, which then would display some of your content.
Even though you have
NSLog(#"Row selected: %d", indexPath.row);
in your method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath*)indexPath
That's not the method that actually detects a cell selection. You should use:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
which is a method from TableViewDelegate, and not TableViewDataSource. Your controller needs to implement both. You also need to connect your tableView to your delegate, in this case, your own controller.
Try NSLogging inside didSelectRowAtIndexPath method to track your selection and further push a new controller, or perform a Storyboard Segue.

Section Header Titles incorrect

I have been trying to set the uiTableViewHeader for my UITableView for a couple of days now with no luck. I don't think I am far off. Currently it shows the section Titles however multiples the number of records by X amount ( I presume my count may be wrong).
I think I need to further configure my cellForRowAtIndexPath method but Im unsure how.
I am a bit confused. I need to group the rowsAtIndexPath to the sections and stop them multiplying.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"atozCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
//Searchbar code is here
NSDictionary *dataDict = [self.sortedArray objectAtIndex:indexPath.section];
cell.textLabel.text = [dataDict objectForKey:#"Title"];
}
return cell;
}
Section Counts
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.sectionArray count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [self.sectionArray objectAtIndex:section];
}
Data Populated from
// Find out the path of recipes.plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"law2" ofType:#"plist"];
// Load the file content and read the data into arrays
self.dataArray = [NSArray arrayWithContentsOfFile:path];
//Sort the array by section
self.sortedArray = [self.dataArray sortedArrayUsingDescriptors:#[
[NSSortDescriptor sortDescriptorWithKey:#"Section" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"Title" ascending:YES]]];
//Section for sorting
self.sectionArray = [self.sortedArray valueForKeyPath:#"Section"];
Always you are sending index of the object. So please try to use this one
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [self.tableDataIndexTitles objectAtIndex:index];
}

UITableView returns the same items on each section

I created a table with sections. Each section has a date (2014-03-23) as a title and under each date I want to populate a list of games to be played that day. When I run the app the table gets the section title fine (date of game), but every section has the same matches list. I want to have the games match under the section date.
I know i need to include indexPath.section in the CellForRowsAtIndexPath but I'm having a hard time figuring it out.
Here's my code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return gamesArray.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
uniqueArray = [[NSOrderedSet orderedSetWithArray:dateSection] array];
return [uniqueArray count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [self.dateSection objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSString *CellIdentifier = [NSString stringWithFormat:#"games cell-%ld-%ld", (long)indexPath.section, (long)indexPath.row];
static NSString *CellIdentifier = #"games cell";
//NSString *CellIdentifier = [NSString stringWithFormat:#"cell-%d-%d", indexPath.section, indexPath.row];
CustomInboxCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = (CustomInboxCell *)[[CustomInboxCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
PFObject *post = [gamesArray objectAtIndex:indexPath.row];
[cell.teamsLabel setText:[post objectForKey:#"teams"]];
[cell.liveRepeatLabel setText:[post objectForKey:#"liveRepeat"]];
[cell.gameTimeLabel setText:[post objectForKey:#"gameTime"]];
return cell;
}
Any help would be greatly appreciated.
//======================================================
//I decided to use a predicate to filter and get the number of items per date(Number of games per date)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *sectionTitle = [uniqueArray objectAtIndex:section];
if (section >=0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"gameDate == %#",sectionTitle];
NSLog(#"section name = %#", sectionTitle);
NSArray *filtered = [gamesArray filteredArrayUsingPredicate:predicate];
NSLog(#"filtered = %#",filtered);
return filtered.count;
}
return 0;
}
//I just need to iterate through every date and return the number of games per date. Any suggestions?
You need a separate array for each section of the table. In numberOfRowsForSection, you need to return a count for the array that corresponds to the given section.
Here's an example. The data for the table is stored in an NSArray called tableData. The array has one entry for each section of the table. Each entry in tableData is an NSDictionary. The NSDictionary has two keys, title and items. The title key corresponds to an NSString that serves as the title for the table section. The items key corresponds to an NSArray that has the row information for the table section.
The table is organized into two sections like this
Fruits
Apples
Oranges
Animals
Dog
Cat
Horse
Cow
Here's the code
#import "MainViewController.h"
#interface MainViewController () <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSArray *tableData;
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
NSDictionary *fruits, *animals;
fruits = #{ #"title" : #"Fruits" , #"items" : #[#"Apples", #"Oranges"] };
animals = #{ #"title" : #"Animals", #"items" : #[#"Dog", #"Cat", #"Horse", #"Cow"] };
self.tableData = #[fruits, animals];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return( self.tableData.count );
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *sectionData = self.tableData[section];
NSArray *items = sectionData[#"items"];
return( items.count );
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSDictionary *sectionData = self.tableData[section];
NSString *title = sectionData[#"title"];
return( title );
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SomeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *sectionData = self.tableData[indexPath.section];
NSArray *items = sectionData[#"items"];
NSString *name = items[indexPath.row];
cell.textLabel.text = name;
return cell;
}
#end
This is a data set problem, you need to have a separate dataset prepared for each section of your tableview and iterate them using the index path (row, section) properties in your cellForRowAtIndexPath method. If you can do NSLog and share your dataset, it would be more helpful to answer accurately. Hope this helps.

Adding sections to tableView using coreData

in my app the user adds cells to a tableView using coreData. This works quite well. But now I want the table view to have sections.
The viewController in which you add new cells look like:
#property (strong) NSManagedObject *travel;
...
-(void)viewDidLoad{
countryName = [[NSArray alloc] initWithObjects:
#"USA", #"England", #"Italy", nil];
countryLabel.text= [countryName objectAtIndex:[picker selectedRowInComponent:0]];
}
- (IBAction)save:(id)sender {
[self.travel setValue:countryLabel.text forKey:#"country"];
}
and in the viewController which displays the cells in a tableView:
#property (strong) NSMutableArray *travelAll;
...
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"position == %#",_positionString];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Travel"];
[fetchRequest setPredicate : predicate ];
self.travelAll = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
...
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section
{ NSArray* headers = [NSArray arrayWithObjects:#"USA",#"England","Italy",nil];
return [headers objectAtIndex:section];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.travelAll count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSManagedObject *travel = [self.travelAll objectAtIndex:indexPath.row];
...
return cell;
}
But now my tableView I have just this three sections (headers) but I can't add cell to them.
For example: the user selects USA for his new cell, so this cell should be displayed in the section USA
Your datasource methods are flawed. For example, you are returning the same cell data for each section. There are other problems as well.
It is much better to use a NSFetchedResultsController. Start from the Apple templates (you get that if you create a new project and choose "Use Core Data"), that employ the fetched results controller.
Your section design becomes very simple then: it is enough to simply specify the sectionNameKeyPath property.

ios: uitableview section header anchor to top of table

i'm trying to make a table with multiple section (like contact app)
everything went well and i've created custom section header on top of each section displaying the character representing this section..the problem is i want it to be like Contact exactly where the header stay on the top till the next header collapse with it ...how can this happen
i'm using the following code (to make it easier for you to figure out
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [stateIndex count];
}
- (UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger)section
{
UILabel *sectionHeader = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
sectionHeader.backgroundColor = [UIColor clearColor];
sectionHeader.font = [UIFont boldSystemFontOfSize:18];
sectionHeader.textColor = [UIColor whiteColor];
sectionHeader.text = [stateIndex objectAtIndex:section];
sectionHeader.textAlignment=UITextAlignmentCenter;
return sectionHeader;
}
//---set the index for the table---
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return stateIndex;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//---get the letter in each section; e.g., A, B, C, etc.---
NSString *alphabet = [stateIndex objectAtIndex:section];
//---get all states beginning with the letter---
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *states = [resultPoets filteredArrayUsingPredicate:predicate];
//---return the number of states beginning with the letter---
return [states count];
}
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
PoemsCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
int row = indexPath.row;
//---get the letter in the current section---
NSString *alphabet = [stateIndex objectAtIndex:[indexPath section]];
//---get all states beginning with the letter---
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *states = [resultPoets filteredArrayUsingPredicate:predicate];
if ([states count]>0) {
//---extract the relevant state from the states object---
NSString *cellValue = [states objectAtIndex:row];
cell.poemText.text = cellValue;
}
return cell;
}
This should work automatically if you use the Table View Style "Plain" and not "Grouped".
From the documentation:
UITableViewStylePlain: A plain table view. Any section headers or
footers are displayed as inline separators and float when the table
view is scrolled.
UITableViewStyleGrouped: A table view whose sections present distinct
groups of rows. The section headers and footers do not float.

Resources