I'm working on a tableview that displays data about a company. I want to divide the data over 3 sections, to make it look more organized.
The data about a company is retreived from a mysql database and I receive it in one array, which looks like this:
{
companyAdress = "the street 9";
companyCity = "city";
companyFacebook = "facebook.com/companyname";
companyName = "name";
companyPhoneNumber = "0123 456 789";
companyTwitter = "www.twitter.com/companyname";
companyWebsite = "www.companyname.com";
companyZip = "0000 AA";
imageNumber = "3067913";
}
I want the companyName and imageNumber in the first section, the companyAdress, companyZip and companyCity in the second, and all the remaining variables in the third section.
I do not know how to properly do this, and I haven't found a useful answer/solution for this on SO or any other website I know.
How to I do this? any help, sample code and/or tutorial would be much appreciated, thank you in advance!
One approach would be to separate the data when you receive it into a two-dimensional array. So the array's first entry would be an array holding companyName and imageNumber, and so on.
With this implementation, numberOfSectionsInTableView would simply return myArray.count and numberOfRowsInSection would return myArray[section].count.
To access the appropriate values from there, you would do something like ((NSMutableArray*)myArray[indexpath.section])[indexpath.row]
You must use a Array of NSDictionary items,
then you get info for sections and tables rows.
adding a key for each record type.
This is a sample project for explain the use of NSArray and NSDictonary, I hope this help you.
You can download the xcode project from here http://www.germinara.it/download/FGTestTableView.zip and this is the result of the sample http://www.germinara.it/download/FGtesttableview.png
#import <UIKit/UIKit.h>
#interface FGViewController : UIViewController <UITableViewDataSource,UITableViewDelegate> {
NSMutableArray* records;
}
#property(nonatomic,strong) IBOutlet UITableView *tblRecordsList;
-(void) buildDataSource; //Build the datasource for the tableview
#end
#import "FGViewController.h"
#interface FGViewController ()
#end
#implementation FGViewController
#synthesize tblRecordsList;
- (void)viewDidLoad
{
[super viewDidLoad];
records = [[NSMutableArray alloc] init];
//Load data into array used as datasource
[self buildDataSource];
self.tblRecordsList.dataSource=self;
self.tblRecordsList.delegate=self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
//Load sample data
-(void) buildDataSource{
NSMutableDictionary* dict= nil;
[records removeAllObjects];
//Fill data source with your data
//Data to put on first section
dict=[NSMutableDictionary dictionaryWithCapacity:0];
[dict setObject:#"0" forKey:#"idsection"];
[dict setObject:#"company1" forKey:#"companyName"];
[dict setObject:#"picture1" forKey:#"imageNumber"];
[records addObject:dict]; //Add items to array
//Data to put on second section
dict=[NSMutableDictionary dictionaryWithCapacity:0];
[dict setObject:#"1" forKey:#"idsection"];
[dict setObject:#"address1" forKey:#"companyAdress"];
[dict setObject:#"zip1" forKey:#"companyZip"];
[dict setObject:#"city1" forKey:#"companyCity"];
[records addObject:dict]; //Add items to array
//Data to put on other section
dict=[NSMutableDictionary dictionaryWithCapacity:0];
[dict setObject:#"2" forKey:#"idsection"];
[dict setObject:#"facebook1" forKey:#"companyFacebook"];
[dict setObject:#"phone1" forKey:#"companyPhoneNumber"];
[dict setObject:#"twitter1" forKey:#"companyTwitter"];
[dict setObject:#"website1" forKey:#"companyWebsite"];
[records addObject:dict]; //Add items to array
}
//Get Dictionary using section key (idsection)
-(NSDictionary *) dictionaryForSection:(NSInteger) section{
for (NSDictionary *dict in records){
if(section == [[dict valueForKey:#"idsection"] intValue]){
return dict;
}
}
return nil;
}
//Table View Delegate
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"myCellReuseID"];
NSDictionary * dict = [self dictionaryForSection:indexPath.section]; //Get request dictionary info
//Process data for first section
if(indexPath.section == 0){
if(indexPath.row == 0)
cell.textLabel.text=[dict valueForKey:#"companyName"];
if(indexPath.row == 1)
cell.textLabel.text=[dict valueForKey:#"imageNumber"];
}
//Process data for second section
if(indexPath.section == 1){
if(indexPath.row == 0)
cell.textLabel.text=[dict valueForKey:#"companyAdress"];
if(indexPath.row == 1)
cell.textLabel.text=[dict valueForKey:#"companyZip"];
if(indexPath.row == 2)
cell.textLabel.text=[dict valueForKey:#"companyCity"];
}
//Process data for other section
if(indexPath.section == 2){
if(indexPath.row == 0)
cell.textLabel.text=[dict valueForKey:#"companyFacebook"];
if(indexPath.row == 1)
cell.textLabel.text=[dict valueForKey:#"companyPhoneNumber"];
if(indexPath.row == 2)
cell.textLabel.text=[dict valueForKey:#"companyTwitter"];
if(indexPath.row == 3)
cell.textLabel.text=[dict valueForKey:#"companyWebsite"];
}
return cell;
}
//Number of sections (first,second and other => 3)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;
}
- (NSString *)tableView:(UITableView *)theTableView titleForHeaderInSection:(NSInteger)section
{
NSString * sectionTitle =#"";
switch (section) {
case 0:
sectionTitle = #"title first section";
break;
case 1:
sectionTitle = #"title second section";
break;
case 2:
sectionTitle = #"title other section";
break;
default:
break;
}
return sectionTitle;
}
//Count number of record for sections
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int nRecords=0;
int idSection =0;
//Count number of items for specified section
for (NSDictionary *dict in records){
idSection = [[dict valueForKey:#"idsection"] intValue];
if(section == idSection){
nRecords = [[dict allKeys] count] -1 ; //All dictionary Keys - 1 (the first key "idsection")
}
}
return nRecords;
}
#end
Related
Hello I have created one of my application in which i have implemented sorting functionality in a table view The sorting method is working fine on iOS 4 and 5 but when I try to test the application on iOS 6, it shows an error in the sorting method on iOS 6
Please help
Method :-
-(void)setupIndexData{
self.arrayOfCharacters =[[NSMutableArray alloc]init];
self.objectForCharacter=[[NSMutableDictionary alloc]init];
NSNumberFormatter *formatter =[[NSNumberFormatter alloc]init];
NSMutableArray *arrayOfNames =[[NSMutableArray alloc]init];
NSString *numbericSection = #"#";
NSString *firstLetter;
for (NSDictionary *item in self.mCompanyarray) {
firstLetter = [[[item valueForKey:#"Company"]description] substringToIndex:1];
// Check if it's NOT a number
if ([formatter numberFromString:firstLetter] == nil) {
/**
* If the letter doesn't exist in the dictionary go ahead and add it the
* dictionary.
*
* ::IMPORTANT::
* You HAVE to removeAllObjects from the arrayOfNames or you will have an N + 1
* problem. Let's say that start with the A's, well once you hit the
* B's then in your table you will the A's and B's for the B's section. Once
* you hit the C's you will all the A's, B's, and C's, etc.
*/
if (![objectForCharacter objectForKey:firstLetter]) {
[arrayOfNames removeAllObjects];
[arrayOfCharacters addObject:firstLetter];
}
[arrayOfNames addObject:item];
/**
* Need to autorelease the copy to preven potential leak. Even though the
* arrayOfNames is released below it still has a retain count of +1
*/
[objectForCharacter setObject:[[arrayOfNames copy] autorelease] forKey:firstLetter];
} else {
if (![objectForCharacter objectForKey:numbericSection]) {
[arrayOfNames removeAllObjects];
[arrayOfCharacters addObject:numbericSection];
}
[arrayOfNames addObject:item];
[objectForCharacter setObject:[[arrayOfNames copy] autorelease] forKey:numbericSection];
}
}
[formatter release];
[arrayOfNames release];
[self.mCompaniesTableView reloadData];
}
Thanks
I'd use UILocalizedIndexedCollation to sort and index your data. That way, your app can support multiple languages etc.
Note: I haven't tested the code below, but the theory is there.
First, create a #property to store the indexed data:
#property (nonatomic, strong) NSDictionary *indexedSections;
Set up your table like this:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//we use sectionTitles and not sections
return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self.indexedSections objectForKey:[NSNumber numberWithInteger:section]] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
BOOL showSection = [[self.indexedSections objectForKey:[NSNumber numberWithInteger:section] count] != 0;
//only show the section title if there are rows in the section
return (showSection) ? [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:section] : nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id object = [[self.indexedSections objectForKey:[NSNumber numberWithInteger:indexPath.section]] objectAtIndex:indexPath.row];
// configure the cell
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
//sectionForSectionIndexTitleAtIndex: is a bit buggy, but is still useable
return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}
And finally index like this:
- (void) setupIndexData
{
// asynchronously sort
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
// create a dictionary to store an array of objects for each section
NSMutableDictionary *tempSections = [NSMutableDictionary dictionary];
// iterate through each dictionaey in the list, and put them into the correct section
for (NSDictionary *item in self.mCompanyarray)
{
// get the index of the section (Assuming the table index is showing A-#)
NSInteger indexName = [[UILocalizedIndexedCollation currentCollation] sectionForObject:[item valueForKey:#"Company"] collationStringSelector:#selector(description)];
NSNumber *keyName = [NSNumber numberWithInteger:indexName];
// if an array doesnt exist for the key, create one
NSMutableArray *arrayName = [tempSections objectForKey:keyName];
if (arrayName == nil)
{
arrayName = [NSMutableArray array];
}
// add the dictionary to the array (add the actual value as we need this object to sort the array later)
[arrayName addObject:[item valueForKey:#"Company"]];
// put the array with new object in, back into the dictionary for the correct key
[tempSections setObject:arrayName forKey:keyName];
}
/* now to do the sorting of each index */
NSMutableDictionary *sortedSections = [NSMutableDictionary dictionary];
// sort each index array (A..Z)
[tempSections enumerateKeysAndObjectsUsingBlock:^(id key, id array, BOOL *stop)
{
// sort the array - again, we need to tell it which selctor to sort each object by
NSArray *sortedArray = [[UILocalizedIndexedCollation currentCollation] sortedArrayFromArray:array collationStringSelector:#selector(description)];
[sortedSections setObject:[NSMutableArray arrayWithArray:sortedArray] forKey:key];
}];
// set the global sectioned dictionary
self.indexedSections = sortedSections;
dispatch_async(dispatch_get_main_queue() ,^{
// reload the table view (on the main thread)
[self.mCompaniesTableView reloadData];
});
});
}
If this is a repost, I apologize, but I have been scouring the net and cant seem to find anything that works. I have a list of workouts that I display in a tableview that are gathered in plists in the bundle. There is a also a separate tab that I have that allows a user to build their own workouts and save them in the documents folder plist file. Once they are saved, they are added to the table view. In the simulator, everyuhting works fine. But on the actual device, it is not updated unless I close the program for an extended period of time, reload the program from xcode, or turn the phone off. I have tried adding [[self tableview] reload] to "viewDidLoad", "viewWillappear", and "viewDidAppear" and none of them work. Once again, the file is saved, the updating does work in the simulator, and it doesn't update in the phone right away. Any suggestions? Thanks.
Edit: i know it is a long piece of code, but should be straight forward (hopefully lol)
#import "BIDWODList.h"
#import "BIDWODDetails.h"
#define kFileName #"SavedDFWorkouts.plist"
#interface BIDWODList ()
#end
#implementation BIDWODList
#synthesize names;
#synthesize savedNames;
#synthesize keys;
#synthesize details;
#synthesize wodType;
#synthesize benchmarkGirls;
#synthesize theNewGirls;
#synthesize heroes;
#synthesize savedDFGWorkouts;
#synthesize chosenWOD;
#synthesize chosenDetails;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *buildBenchmarkGirls = [[NSMutableArray alloc] init];
NSMutableArray *buildTheNewGirls = [[NSMutableArray alloc] init];
NSMutableArray *buildHeroes = [[NSMutableArray alloc] init];
NSBundle *bundle = [NSBundle mainBundle];
NSURL *plistURL = [bundle URLForResource:#"CrossfitWOD" withExtension:#"plist"];
//put the contents of the plist into a NSDictionary, and then into names instance variable
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL];
self.names = dictionary;
//take all the keys in the dictionary and make an array out of those key names
self.keys = [self.names allKeys];
for (NSString *nameCheck in keys){
self.details = [names valueForKey:nameCheck];
if ([[self.details valueForKey:#"Type"] isEqualToString:#"The Benchmark Girls"]) {
[buildBenchmarkGirls addObject:nameCheck];
}else if ([[self.details valueForKey:#"Type"] isEqualToString:#"The New Girls"]) {
[buildTheNewGirls addObject:nameCheck];
}else {
[buildHeroes addObject:nameCheck];
}
}
NSString *filePath = [self dataFilePath];
NSMutableDictionary *savedWorkout = [[NSMutableDictionary alloc]initWithContentsOfFile:filePath];
self.savedNames = savedWorkout;
self.savedDFGWorkouts = [[savedWorkout allKeys] sortedArrayUsingSelector:#selector(compare:)];
self.benchmarkGirls = [buildBenchmarkGirls sortedArrayUsingSelector:#selector(compare:)];
self.theNewGirls = [buildTheNewGirls sortedArrayUsingSelector:#selector(compare:)];
self.heroes = [buildHeroes sortedArrayUsingSelector:#selector(compare:)];
//[[self tableView] reloadData]; //reloads the data in case a DFG workout was saved
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.names = nil;
self.keys = nil;
self.benchmarkGirls = nil;
self.theNewGirls = nil;;
self.heroes = nil;
self.details = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSString *)dataFilePath {
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFileName];
}
-(void)viewDidAppear:(BOOL)animated{
[[self tableView] reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 4;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (section == 0) {
return [benchmarkGirls count];
}else if (section == 1){
return [theNewGirls count];
}else if (section == 2){
return [heroes count];
}else{
return [savedDFGWorkouts count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier];
}
if (section == 0) {
cell.textLabel.text = [benchmarkGirls objectAtIndex:row];
}else if (section == 1) {
cell.textLabel.text = [theNewGirls objectAtIndex:row];
}else if (section == 2) {
cell.textLabel.text = [heroes objectAtIndex:row];
}else{
cell.textLabel.text = [savedDFGWorkouts objectAtIndex:row];
}
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0) {
return #" The Benchmark Girls";
}else if (section == 1){
return #"The New Girls";
}else if (section ==2){
return #"The Heroes";
}else{
return #"Saved DFG Workouts";
}
}
#pragma mark - Table view delegate
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
BIDWODDetails *destination = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
if (section == 0) {
self.chosenWOD = [self.benchmarkGirls objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else if (section == 1) {
self.chosenWOD = [self.theNewGirls objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else if (section ==2) {
self.chosenWOD = [self.heroes objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else {
self.chosenWOD = [self.savedDFGWorkouts objectAtIndex:row];
self.chosenDetails = [savedNames objectForKey:chosenWOD];
}//end if
//self.chosenDetails = [names objectForKey:chosenWOD];
//[destination setValue:chosenWOD forKey:#"chosenWOD"];
//[destination setValue:chosenDetails forKey:#"chosenDetails"];
destination.chosenWOD = self.chosenWOD;
destination.chosenDetails = self.chosenDetails;
}
#end
Different behaviour between the simulator and the device is often related to incorrect case being used in filenames - the simulator isn't case sensitive, and the device is. Check that you have the correct case used everywhere you reference the plist file.
Alternatively, on the simulator you are able to write directly to the application bundle, but on the device this is not possible and you can only write to certain directories in your application's sandbox, typically the documents directory. You would normally copy a plist to the documents directory on first run, and use that file thereafter.
If I understand right your code you load plist file only in viewDidLoad, but most likely this function called only when you first time load your view. To make it work you should load plist
in viewDidAppear. Something like this:
- (void)viewDidAppear {
NSBundle *bundle = [NSBundle mainBundle];
NSURL *plistURL = [bundle URLForResource:#"CrossfitWOD" withExtension:#"plist"];
//put the contents of the plist into a NSDictionary, and then into names instance variable
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL];
self.names = dictionary;
//take all the keys in the dictionary and make an array out of those key names
self.keys = [self.names allKeys];
for (NSString *nameCheck in keys){
self.details = [names valueForKey:nameCheck];
if ([[self.details valueForKey:#"Type"] isEqualToString:#"The Benchmark Girls"]) {
[buildBenchmarkGirls addObject:nameCheck];
}else if ([[self.details valueForKey:#"Type"] isEqualToString:#"The New Girls"]) {
[buildTheNewGirls addObject:nameCheck];
}else {
[buildHeroes addObject:nameCheck];
}
}
NSString *filePath = [self dataFilePath];
NSMutableDictionary *savedWorkout = [[NSMutableDictionary alloc]initWithContentsOfFile:filePath];
self.savedNames = savedWorkout;
self.savedDFGWorkouts = [[savedWorkout allKeys] sortedArrayUsingSelector:#selector(compare:)];
[self.tableView reloadData];
}
If it works in the Simulator and does not on the phone, almost for sure the problem is a timing issue. Saving files on a real phone takes much longer than on the simulator.
You should do the following:
when you save a file, log it, and log the return code from the save. If the way you save does not provide a return code, use NSFileManager to verify the file is in fact where it should be and even the size of it. This takes time to do but you should do it.
when your table is asking for the number of this and that, log it, and lot what is returned. You may find that that this comes before the files are saved.
It takes time and effort, but if you start logging all relevant things, you can find it. I just spend 6 hours today tracking down a race condition I had thought could never happen, and it was only after looking at a huge trail of messages that I was able to see the problem.
Almost for sure you will see that either file is not saved, its not where you thought it was, or that the phone timing means some events happen later than they do in the Simulator.
I have a UITableView populated by a SQLite database. I added Section-based Grouping using the sectionIndexTitlesForTableView delegate method today and now when a Cell is selected, the String for indexPath.row is not the same as the text in the selected Cell.
My Code works like this.
I create an Array that holds the businesses from the SQLite database.
I sort that Array alphabetically.
I create an Array of letters of the Alphabet using only the letters of the Alphabet that businesses in the database begin with.
I use that Array, along with an NSPredicate to provide Grouped Header views which group the businesses by their first letter, alphabetically.
The Selected Row is written to the NSUserDefaults file, and a View Controller is pushed (iPhone), or an Observer is added for that key (iPad).
Unfortunately, since adding the header views, indexPath.row now returns a completely different string to that of the TextLabel of the selected Cell, and so a different Business' information is displayed.
Here are the important blocks of code for the main arrays.
- (void)viewDidLoad
{
// Lots of code...
arrayName = [[NSMutableArray alloc] init];
NameSet = [[NSMutableSet alloc] init];
sortedArray = [arrayName sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
alphabet = [[NSMutableArray alloc] init];
[alphabet addObject:#"{search}"];
for (int i=0; i<[sortedArray count]-1; i++)
{
char alphabetUni = [[sortedArray objectAtIndex:i] characterAtIndex:0];
NSString *uniChar = [NSString stringwithFormat:#"%c", alphabetUni];
if (![alphabet containsObject:uniChar])
{
[alphabet addObject:uniChar];
}
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [alphabet count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = 0;
NSString *alpha = [alphabet objectAtIndex:section];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alpha];
businesses = [sortedArray filteredArrayUsingPredicate:predicate];
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]){
rows = [self.searchResults count];
}
else {
rows = [businesses count];
}
return rows;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection (NSInteger)section
{
return [alphabet objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSString *alpha = [alphabet objectAtIndex:indexPath.section];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alpha];
businesses = [sortedArray filteredArrayUsingPredicate:predicate];
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]){
cell.textLabel.text =
[self.searchResults objectAtIndex:indexPath.row];
}
else{
NSString *cellValue = [businesses objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *selected = nil;
if (tableView == self.tableView)
{
selected = [businesses objectAtIndex:indexPath.row];
}
else if (tableView == searchDis.searchResultsTableView)
{
selected = [filteredData objectAtIndex:indexPath.row];
}
[def setObject:selected forKey:#"NameChoiceDetail"];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
[self performSegueWithIdentifier:#"NameDetailPush" sender:self];
}
}
// Please excuse my horribly written code. I've only been working with Objective-C for 4 months, and Programming for about 8 months. Any suggestions/optimisations will be duly noted.
Your table view uses sections but your implementation of tableView:didSelectRowAtIndexPath: doesn't evaluate the section of the index path. So the code is missing something.
Furthermore, I find that your use of the businesses variable (it's probably an instance variable) very strange. It is assigned a value in tableView:cellForRowAtIndexPath: but not in tableView:didSelectRowAtIndexPath: even though it is used there. So the outcome if the latter depends on what table cell was displayed last and as a consequence it depends on scrolling user interaction. That might be the reason why the outcome looks rather random.
I have displayed the datas in grouped table view. The data's are displayed in the table view from XML parsing. I have 2 section of the table view, the section one has three rows and section two has two rows.
section 1 -> 3 Rows
section 2 - > 2 Rows.
Now i want to check, if anyone of the string is empty then i should remove the empty cells, so i have faced some problems, if i have removed any empty cell, then it will changed the index number. So how can i check, anyone of the field is empty?, Because some times more number of empty field will come, so that the index position will be change. So please send me any sample code or link for that? How can i achieve this?
Sample code,
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {
if([userEmail isEqualToString:#" "] || [phoneNumber isEqualToString:#" "] || [firstName isEqualToString:#" "])
{
return 2;
}
else {
return 3;
}
}
if (section == 1) {
if(![gradYear isEqualToString:#" "] || ![graduate isEqualToString:#" "]) {
return 1;
}
else
{
return 2;
}
return 0;
}
Please Help me out!!!
Thanks.
As per my understanding, you dont want to add the row where data is empty, so ill suggest you should perpare the sections data before telling the table view about the sections and rows.
So, may be following code can help you..., i have tested it you just need to call the method "prepareSectionData" from "viewDidLoad" method and define the section arrays in .h file.
- (void) prepareSectionData {
NSString *userEmail = #"";
NSString *phoneNumber = #"";
NSString *firstName = #"";
NSString *gradYear = #"";
NSString *graduate = #"";
sectionOneArray = [[NSMutableArray alloc] init];
[self isEmpty:userEmail]?:[sectionOneArray addObject:userEmail];
[self isEmpty:phoneNumber]?:[sectionOneArray addObject:phoneNumber];
[self isEmpty:firstName]?:[sectionOneArray addObject:firstName];
sectionTwoArray = [[NSMutableArray alloc] init];
[self isEmpty:gradYear]?:[sectionTwoArray addObject:gradYear];
[self isEmpty:graduate]?:[sectionTwoArray addObject:graduate];
}
-(BOOL) isEmpty :(NSString*)str{
if(str == nil || [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0)
return YES;
return NO;
}
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(section == 0){
return [sectionOneArray count];
} else if (section == 1) {
return [sectionTwoArray count];
}
return 0;
}
// Customize the appearance of table view cells.
- (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];
}
// Configure the cell.
if(indexPath.section == 0){
cell.textLabel.text = [sectionOneArray objectAtIndex:indexPath.row];
} else if (indexPath.section == 1) {
cell.textLabel.text = [sectionTwoArray objectAtIndex:indexPath.row];
}
return cell;
}
#Pugal Devan,
Well, you can keep the data in one array, but the problem in that case is, you have to take care of array bounds and correct indexes for different sections. For each section indexPath.row will start from index 0, and if your data is in single array, you have to manage the row index by your self. But still if you want to keep it, you can do like:
int sectionOneIndex = 0;
int sectionTwoIndex = 3;
NSMutableArray *sectionArray = [[NSMutableArray alloc] initWithObjects:#"email", #"Name", #"address", #"zipCode", #"country", nil];
Above two integers represents the starting position of elements of your different sections. First 3 objects from the section Array are the part of section One, and last two objects are the part of section two. Now you need to return correct row count.
For that you may write:
if(section == 0) return [sectionArray count] - (sectionTwoIndex-1); //returns 3
else if(section == 1) return [sectionArray count] - sectionTwoIndex; //returns 2
OR if your count is static you may put constant values in return.
And at the time you read from array, you will just add this index in row value, which will return the correct position of your element for the current cell.
// Customize the appearance of table view cells.
- (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];
}
// Configure the cell.
if(indexPath.section == 0){
cell.textLabel.text = [sectionArray objectAtIndex:indexPath.row + sectionOneIndex];
} else if (indexPath.section == 1) {
cell.textLabel.text = [sectionArray objectAtIndex:indexPath.row + sectionTwoIndex];
}
return cell;
}
i am using this query to get the data by ASC order
select * from list_tbl where cat_id=%d order by names ASC
now my table view shows data based on ASC order
then i used this to get the letters from A to Z on right side
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)help
{
return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:help];
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}
now my problem is how to divide data based on section header like all A content goes to A and then B till Z and when user click on any alphabet on right side it should goes to that section
// UPDATES ///////////////
-(void)setUpRecordsForIndexing
{
for (NSString * recordName in appDelegate.catLists)//where app.catList contains all the value
{
NSString *firstLetter = ([recordName length] ==0)?miscKey:[[recordName substringToIndex:1]uppercaseString];
/*if(![firstLetter beginsWithCharacterInSet:[NSCharacterSet letterCharacterSet]] || [recordName isEqualToString:#""] || recordName == nil )
firstLetter = miscKey ;
*/
NSMutableArray *indexArray = [IndexedRecords objectForKey:firstLetter];
if (indexArray == nil)
{
indexArray = [[NSMutableArray alloc] init];
[IndexedRecords setObject:indexArray forKey:firstLetter];
[IndexLetters addObject:firstLetter];
[indexArray release];
}
[indexArray addObject:record];// this is not workking
// NSLog(#" index array is %#",indexArray);
}
}
my INDEXRECORD is not showing correct value
i can now divide the section based on ABCD but each sections are having same content , what i am doing wrong
for example: say RecordsArray contains your all the records, now in table view datasource method numberOfSectionsInTableView call one more method to index your all the records like below
-(void)setUpRecordsForIndexing
{
if(IndexedRecords)
{
[IndexedRecords release];
IndexedRecords = nil;
}
if(IndexLetters)
{
[IndexLetters release];
IndexLetters = nil;
}
IndexedRecords = [[NSMutableDictionary alloc] init];
IndexLetters = [[NSMutableArray alloc] init];
NSString *miscKey = #"#";
for (NSString * recordName in RecordsArray)
{
NSString *firstLetter = ([recordName length] ==0)?miscKey:[[recordName substringToIndex:1]uppercaseString];
if(![firstLetter beginsWithCharacterInSet:[NSCharacterSet letterCharacterSet]] || [recordName isEqualToString:#""] || recordName == nil )
firstLetter = miscKey ;
NSMutableArray *indexArray = [mIndexedRecords objectForKey:firstLetter];
if (indexArray == nil)
{
indexArray = [[NSMutableArray alloc] init];
[IndexedRecords setObject:indexArray forKey:firstLetter];
[IndexLetters addObject:firstLetter];
[indexArray release];
}
[indexArray addObject:record];
}
}
and in numberOfSectionsInTableView return the count of IndexLetters. I hope this will solve your problem.
While indexing your records, keep your records in a dictionary say IndexedRecords. Such that, for key "A" set the array of records begin with letter "A". And while populating the table view
[[IndexedRecords objectForKey:[IndexLetters objectAtIndex:indexPath.section]]objectAtIndex:indexPath.row]
IndexLetters is also an array containing your index letters for the current list.