How to manage UITableView if number of sections are not confirmed - ios

I am using UITableView in which number of sections are created dynamically according to the data. From 1 to 12. Section names are the names of months. How can I check w.r.t to the sections name. My code is
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [sectionArray count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [sectionArray objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int count = 0;
for(int counter=0; counter<[sectionArray count]; counter++)
{
NSString *month = [sectionArray objectAtIndex:counter];
if([month isEqualToString:#"October"])
{
count = [octoberArray count];
}
else if([month isEqualToString:#"November"])
{
count = [novemberArray count];
}
else if([month isEqualToString:#"December"])
{
count = [decemberArray count];
}
else if([month isEqualToString:#"January"])
{
count = [januaryArray count];
}
else if([month isEqualToString:#"February"])
{
count = [febuaryArray count];
}
else if([month isEqualToString:#"March"])
{
count = [marchArray count];
}
else if([month isEqualToString:#"April"])
{
count = [aprilArray count];
}
else if([month isEqualToString:#"May"])
{
count = [mayArray count];
}
else if([month isEqualToString:#"June"])
{
count = [juneArray count];
}
else if([month isEqualToString:#"July"])
{
count = [julyArray count];
}
else if([month isEqualToString:#"August"])
{
count = [augustArray count];
}
else
{
count = [septemberArray count];
}
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
HistoryCell *cell = (HistoryCell *)[tableView dequeueReusableCellWithIdentifier:#"historyCell"];
if(cell == nil)
{
cell = [[[NSBundle mainBundle]loadNibNamed:#"HistoryCell" owner:self options:nil] objectAtIndex:0];
}
for(int counter=0; counter<[sectionArray count]; counter++)
{
NSString *month = [sectionArray objectAtIndex:counter];
if([month isEqualToString:#"October"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[octoberGlassesArray objectAtIndex:indexPath.row]];
cell.unitLabel.text = #"Unit";
cell.dateLabel.text = [octoberArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"November"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[novemberGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [novemberArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"December"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[decemberGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [decemberArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"January"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[januaryGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [januaryArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"February"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[febuaryGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [febuaryArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"March"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[marchGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [marchArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"April"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[aprilGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [aprilArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"May"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[mayGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [mayArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"June"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[juneGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [juneArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"July"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[julyGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [julyArray objectAtIndex:indexPath.row];
}
else if([month isEqualToString:#"August"])
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[augustGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [augustArray objectAtIndex:indexPath.row];
}
else
{
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[septemberGlassesArray objectAtIndex:indexPath.row]];
cell.dateLabel.text = [septemberArray objectAtIndex:indexPath.row];
}
}
return cell;
}
The application crashes. How can I fix this issue?

I'm sure you don't clearly understand how UITableViewDataSource works. But if I understand your idea correctly the code below should fix the problem:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [sectionArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *yourMonthArray = //Here get an array for adequate month
return [yourMonthArray count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSArray *arr = #[#"January",#"February",...,#"December"];
// asserts are optional. Just for sure you initialized your data well.
NSAssert(arr.count == 12, #"The number of months is not valid");
NSAssert(arr.count == [sectionArray count], #"Number of months is different than number of sections");
return arr[section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
HistoryCell *cell = (HistoryCell *)[tableView dequeueReusableCellWithIdentifier:#"historyCell"];
if(cell == nil)
{
// Please consider using UINib instread.
cell = [[[NSBundle mainBundle]loadNibNamed:#"HistoryCell" owner:self options:nil] objectAtIndex:0];
}
NSString *month = [sectionArray objectAtIndex:indexpath.section];
cell.glassesLabel.text = [NSString stringWithFormat:#"%# Glasses",[octoberGlassesArray objectAtIndex:indexPath.section]];
cell.unitLabel.text = #"Unit";
NSArray *yourMonthArray = //Here get an array for adequate month
cell.dateLabel.text = yourMonthArray[indexPath.row];
return cell;
}

Related

Populating uitableviewcell after filtering, cell content always the same

I'm working on a simple problem which is populating UITableViewCells after searching and filtering.
Here is some code for populating the cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
.... etc
if ([self.searchController isActive] && (![self.searchController.searchBar.text isEqualToString:#""])) {
NSArray *results = [self.searchResults mutableCopy];
if (results.count == 0) {
// do nothing
} else {
for (NSInteger i = 0; i < results.count; i ++) {
NSString *fullName = [results objectAtIndex:i];
((SSContactTableViewCell *)cell).fullNameLabel.text = fullName;
}
}
} else { .. etc
I separated a lot of my code so I could debug it, and here is my results when I search for the letter "t":
I can see that I do have 6 items in my results array, with all contains the letter 't'.
The rest looks good as well, firstName is "Clayton Farr" and cell content is "Clayton Farr"
However, on my app, only the name "Hally Wernstorm" fills.
I don't want this to happen of course, so I was wondering where in the code am I getting all "Hally Wernstorm" back?
Some code that I've wrote:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
if (self.contactsButton.selected) {
cell = [tableView dequeueReusableCellWithIdentifier:#"ContactCell" forIndexPath:indexPath];
if ([self.searchController isActive] && (![self.searchController.searchBar.text isEqualToString:#""])) {
NSArray *results = [self.searchResults mutableCopy];
if (results.count == 0) {
// do nothing
} else {
for (NSInteger i = 0; i < results.count; i ++) {
NSString *fullName = [results objectAtIndex:i];
((SSContactTableViewCell *)cell).fullNameLabel.text = fullName;
}
}
} else {
NSArray *sectionArray = [self.contacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", [self.indexTitles objectAtIndex:indexPath.section]]];
NSString *fullName = [sectionArray objectAtIndex:indexPath.row];
((SSContactTableViewCell *)cell).fullNameLabel.text = fullName;
((SSContactTableViewCell *)cell).specialtyLabel.text = [self.specialities objectAtIndex:indexPath.row];
[((SSContactTableViewCell *)cell).avatarButton setTitle:[NSString initialsOfStrings:[fullName componentsSeparatedByString:#" "]]];
}
}
else if (self.patientsButton.selected) {
cell = [tableView dequeueReusableCellWithIdentifier:#"PatientCell" forIndexPath:indexPath];
NSArray *sectionArray = [self.patients filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", [self.indexTitles objectAtIndex:indexPath.section]]];
((SSPatientTableViewCell *)cell).fullNameLabel.text = [sectionArray objectAtIndex:indexPath.row];
}
else if (self.favouritesButton.selected) {
// cell = [tableView dequeueReusableCellWithIdentifier:#"ContactCell" forIndexPath:indexPath];
}
return cell;
}
#pragma mark - UISearchControllerDelegate
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = searchController.searchBar.text;
if (searchString == nil) {
self.searchResults = [self.contacts mutableCopy];
} else {
self.searchResults = [[NSMutableArray alloc] init];
for (NSString *name in self.contacts) {
if ([name.lowercaseString containsString:searchString.lowercaseString]) {
[self.searchResults addObject:name];
}
}
}
[self.tableView reloadData];
}
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope {
[self updateSearchResultsForSearchController:self.searchController];
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (self.searchController.active) {
if ( self.searchResults.count == 0 && (![self.searchController.searchBar.text isEqualToString:#""]) ) {
return 0;
}
}
return 26;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.contactsButton.selected) {
NSArray *sectionArray = [self.contacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", [self.indexTitles objectAtIndex:section]]];
return [sectionArray count];
} else if (self.patientsButton.selected) {
NSArray *sectionArray = [self.patients filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", [self.indexTitles objectAtIndex:section]]];
return [sectionArray count];
} else if ([self.searchController isActive] && (![self.searchController.searchBar.text isEqualToString:#""])) {
return [self.searchResults count];
}
return 6;
}
Thanks to anyone that can help.
This is not the appropriate way to manage tableView search.
You need to create a filtered array and to reload your tableView based on it each time it changes.
Using for loop is not an correct way.
As you are using for loop you are always getting the same name.
Kindly go through this and use this search bar in objective-c demo

Parse json for sectioned UITableView in iOS

I am trying to display State (in section title) and City (in table rows) from this url. Top Cities will come in first section followed by state and cities. Issue is I am not able to assign respective array of cities for sectioned state title row. Here's what I tried..
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"Json dictionary = %#", json);
self.dictListSateMaster = [json objectForKey:#"RaffleInstanceLocations"];
for (NSDictionary *dict in [self.dictListSateMaster objectForKey:#"listStateMaster"])
{
ViewLocationsObjct *viewLocationsObjct = [[ViewLocationsObjct alloc] init];
viewLocationsObjct.StateNameStr = [dict objectForKey:#"StateName"];
[self.arrayListStateMaster addObject:[dict objectForKey:#"StateName"]];
for (NSDictionary *dictnry in [dict objectForKey:#"listCityMaster"])
{
//*********-- Need corrections here
ViewLocationStateMaster *viewLocNewObjct = [[ViewLocationStateMaster alloc] init];
viewLocNewObjct.CityName = [dictnry objectForKey:#"CityName"];
[self.arrayListCityMaster addObject:viewLocNewObjct];
}
}
for (NSDictionary *dict in [self.dictListSateMaster objectForKey:#"listTopCities"])
{
ViewLocationsObjct *viewLocationsObjct = [[ViewLocationsObjct alloc] init];
viewLocationsObjct.CityName = [dict objectForKey:#"CityName"];
[self.arrayTopCities addObject:viewLocationsObjct];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.arrayListStateMaster.count+1; //+1 to append to top cities section at the top
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"cellId";
ViewLocationsTblCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
if (indexPath.section == 0)
{
ViewLocationsObjct *viewLocationObj = [self.arrayTopCities objectAtIndex:indexPath.row];
cell.locationLabl.text = viewLocationObj.CityName;
}
else
{
//*********-- Need corrections here
//NSString *sectionTitle = [self.arrayListStateMaster objectAtIndex:indexPath.section];
//NSMutableArray *arrayCities = [self.dictListSateMaster objectForKey:sectionTitle];
//cell.locationLabl.text = [arrayCities objectAtIndex:indexPath.row];
ViewLocationStateMaster *viewLoc = [self.arrayListCityMaster objectAtIndex:indexPath.row];
cell.locationLabl.text = viewLoc.CityName;
}
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0)//return top cities for 1st section
{
return self.arrayTopCities.count;
}
else
{
return self.arrayListCityMaster.count;
}
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == 0)
{
return #"Top Cities";
}
else
{
if (self.arrayListStateMaster.count > 0)
{
return [self.arrayListStateMaster objectAtIndex:section-1];//-1 to remove index of top cities section at the top
}
else
{
return #"";
}
}
}
OK so here's how my problem was solved !
NSDictionary *dictRaffleInstLocations = [json objectForKey:#"RaffleInstanceLocations"];
sectionArray = [dictRaffleInstLocations objectForKey:#"listStateMaster"];
topCityArray = [dictRaffleInstLocations objectForKeyedSubscript:#"listTopCities"];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {
return topCityArray.count;
}else
return [[[sectionArray objectAtIndex:section-1]objectForKey:#"listCityMaster"] count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return sectionArray.count+1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == 0) {
return #"Top Cities";
}else
return [[sectionArray objectAtIndex:section-1]objectForKey:#"StateName"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"MyCellLocation";
ViewLocationsTblCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0f)
{
cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *titleString = #"";
if (indexPath.section == 0) {
titleString = [[topCityArray objectAtIndex:indexPath.row]objectForKey:#"CityName"];
}else{
NSArray *cityArray = [sectionArray[indexPath.section-1]objectForKey:#"listCityMaster"];
titleString = [cityArray[indexPath.row]objectForKey:#"CityName"];
}
cell.locationLabl.text = titleString;
return cell;
}

Array empty when trying to populate tableview

I'm trying to create a second section which is where section.indexPath = 0. This section is objects which is generated from distance between two locations which is done in the didUpdateToLocation. When trying to populate the tableview with the objects from the array it shows:
index 0 beyond bounds for empty array'
How can i show the nearStoresArray in the tableview without getting the empty array error.
Here is the cellForRowAtIndexPath. Here it gives an error and say that nearStoresArray is empty. I guess thats because the tableview is showing before the didUpdateToLocation.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (indexPath.section == 0) {
indexNo = [nearStoresArray objectAtIndex:indexPath.row];
NSLog(#"%d", [nearStoresArray count]);
} else if (indexPath.section == 1) {
if (tableView == self.searchDisplayController.searchResultsTableView) {
indexNo = [filteredArray objectAtIndex:indexPath.row];
} else {
indexNo = [storesArray objectAtIndex:indexPath.row];
}
}
cell.textLabel.text = [indexNo valueForKey:#"name"];
return cell;
}
Here is the didUpdateToLocation method. This method creates the nearStoresArray, which works fine.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[locationManager stopUpdatingLocation];
locationManager = nil;
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
for (int i = 0; i < [storesArray count]; i++) {
CLLocationDegrees latitude = [[[storesArray objectAtIndex:i] valueForKey:#"lat"] doubleValue];
CLLocationDegrees longitude = [[[storesArray objectAtIndex:i] valueForKey:#"long"] doubleValue];
CLLocation *checkPosition = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
CLLocationDistance distance = [checkPosition distanceFromLocation:currentLocation];
float distanceInKm = distance / 1000;
if (distanceInKm < 5) {
[nearStoresArray removeAllObjects];
[nearStoresArray addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:
[[storesArray objectAtIndex:i] valueForKey:#"id"], #"id",
[[storesArray objectAtIndex:i] valueForKey:#"name"], #"name",
[[storesArray objectAtIndex:i] valueForKey:#"lat"], #"lat",
[[storesArray objectAtIndex:i] valueForKey:#"long"], #"long",
[[storesArray objectAtIndex:i] valueForKey:#"address"], #"address",
[[storesArray objectAtIndex:i] valueForKey:#"zip"], #"zip"
, nil]];
NSLog(#"%#", nearStoresArray);
}
[self.tableView reloadData];
}
}
}
numberOfRows Method
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section==0) {
return [nearStoresArray count];
} else if (section==1) {
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [filteredArray count];
} else {
return [storesArray count];
}
} else {
return 0;
}
}
You can directly Access Section Like
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) {
return [nearStoresArray count];
}
else if (section == 1) {
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [filteredArray count];
}
else {
return [storesArray count];
}
}
}
I believe you need to update numberOfRowsInSection method, like below -
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) {
return [nearStoresArray count];
}
else if (section == 1) {
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [filteredArray count];
}
else {
return [storesArray count];
}
}
else {
return 0;
}
}

button tag issue with UISearchBar

I need to set a tag for the button created on the table view cell.
I implemented the UISearchBar and it works well.
Issue is after filtering the tableView cell, its indexpath.row changes as I am setting
'button.tag = indexPath.row'.
Is there a way to keep the row number constant for every cell?
Or is there any other solution?
Note: I have multiple sections in one UITableView and isFiltered is BOOL value which indicates user have started to type text in UISearchBar.
Implemented Searching with help of https://github.com/kwylez/IndexedTable
In cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"CheckBoxedCell";
// NSString *cellId = [NSString stringWithFormat:#"Section:%d Row:%d",indexPath.section,indexPath.row];
CheckBoxedCellClass *cell = (CheckBoxedCellClass *)[self.tableViewContact dequeueReusableCellWithIdentifier:cellId];
if(!cell)
{
NSArray *nib;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"CheckBoxedCellClass" owner:self options:nil];
}
else if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"CheckBoxedCellClass_iPad" owner:self options:nil];
}
for (id object in nib)
{
if([object isKindOfClass:[CheckBoxedCellClass class]])
{
cell = (CheckBoxedCellClass *)object;
break;
}
}
cell = [nib objectAtIndex:0];
}
SaveCheckBoxedView *saveContact;
if(isFiltered == YES)
{
saveContact = [filterdArray objectAtIndex:indexPath.row];
cell.nameLabel.text = saveContact.nameString;
}
else
{
saveContact = [mutableArray objectAtIndex:indexPath.row];
cell.nameLabel.text = [[objectsForCharacters objectForKey:[arrayOfCharacters objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
}
//cell.nameLabel.text = saveContact.nameString;
cell.companyLabel.text = saveContact.companyString;
cell.invIdLabel.text = [NSString stringWithFormat:#"%d", saveContact.invitId];
//set fonts
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
[cell.companyLabel setFont:[UIFont italicSystemFontOfSize:10.0]];
}
else
{
[cell.companyLabel setFont:[UIFont italicSystemFontOfSize:14.0]];
}
//handling check box
NSInteger rowNumber = 0;
for(NSInteger i = 0; i < indexPath.section ; i++)
{
rowNumber += [self tableView:self.tableViewContact numberOfRowsInSection:i];
}
rowNumber += indexPath.row;
/*if([indexPath compare:self.lastIndexPath] == NSOrderedSame)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSString *finalIntId = [mutableArrayOfIds objectAtIndex:rowNumber];
NSLog(#"Tagged checked button id = %#", finalIntId);
[arrayOfIds addObject:finalIntId];
}*/
UIButton *checkBox;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(7, 8, 30, 30)];
}
else
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(15, 13, 30, 30)];
}
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
[checkBox addTarget:self action:#selector(checkBoxClicked:event:) forControlEvents:UIControlEventTouchUpInside];
if(isFiltered == YES)
{
checkBox.tag = ;
}
else
{
checkBox.tag = rowNumber;
}
[cell.contentView addSubview:checkBox];
return cell;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
if(isFiltered == YES) {
return Nil;
} else {
NSArray *toBeReturned = [NSArray arrayWithArray:
[#"A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|#"
componentsSeparatedByString:#"|"]];
return toBeReturned;
}
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
if (title == UITableViewIndexSearch) {
CGRect searchBarFrame = self.searchDisplayController.searchBar.frame;
[tableView scrollRectToVisible:searchBarFrame animated:YES];
return -1;
} else {
NSInteger count = 0;
for (NSString *character in arrayOfCharacters) {
if ([character isEqualToString:title]) {
return count;
}
count ++;
}
return 0;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if(isFiltered == YES) {
return 1;
} else {
return [arrayOfCharacters count];
//return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(isFiltered == YES) {
return [filterdArray count];
} else {
//return [mutableArray count];
return [[objectsForCharacters objectForKey:[arrayOfCharacters objectAtIndex:section]] count];
}
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if ([arrayOfCharacters count] == 0) {
return #"";
}
return [NSString stringWithFormat:#"%#", [arrayOfCharacters objectAtIndex:section]];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if(searchText.length == 0)
{
isFiltered = NO;
}
else
{
isFiltered = YES;
filterdArray = [[NSMutableArray alloc] init];
for (SaveCheckBoxedView *contact in mutableArray)
{
NSRange nameRange = [contact.nameString rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(nameRange.location != NSNotFound)
{
[filterdArray addObject:contact];
}
}
}
[self.tableViewContact reloadData];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[filterdArray removeAllObjects];
if(searchString.length > 0)
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [search] %#", self.mySearchBar.text];
for (NSString *key in arrayOfCharacters)
{
NSArray *matches = [objectsForCharacters[key] filteredArrayUsingPredicate:predicate];
[filterdArray addObjectsFromArray:matches];
}
}
return YES;
}
I am describing one way to do so, you may find better way.
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[filterdArray removeAllObjects];
if(searchString.length > 0)
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [search] %#", self.mySearchBar.text];
for (NSString *key in arrayOfCharacters)
{
NSArray *matches = [objectsForCharacters[key] filteredArrayUsingPredicate:predicate];
/****see bellow****/
[filterdArray addObjectsFromArray:matches];
}
}
return YES;
}
Try to find the row number of each object of "matches". that will be the tag of your buttons. Make filterdArray an array of dictionary. Add 2 field to dictionary. one for tag another for value. in cellForRowAtIndexPath.
if(isFiltered == YES)
{
checkBox.tag = [filterdArray objectForKey: #"tag"] ;
}
else
{
checkBox.tag = rowNumber;
}

Filter NSMutableDictionary data in UITableView

I need to filter data in UITableview by text entered in UISearchbar. I followed this example but there data in NSMutableArray and I can't alter it under my requirements. My data is NSMutableDictionary. I'm stuck on this for long time.
My data:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [[documentPaths lastObject] stringByAppendingPathComponent:#"data.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSMutableDictionary *resultDic = [[NSMutableDictionary alloc] init];
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSDictionary *myDict = [NSDictionary dictionaryWithContentsOfFile:path];
sectionKeys = [NSMutableArray new];
sectionsTitle = [NSMutableArray new];
NSArray *tableArray = [myDict objectForKey:#"Black"];
[resultArray addObject:#"Black"];
[resultDic setValue:tableArray forKey:#"Black"];
[sectionsTitle addObject:[NSString stringWithFormat:#"%#", [tableData valueForKey:#"Black"]]];
[sectionCord addObject:[NSString stringWithFormat:#"%#", [tableData valueForKey:#"Coordinates"]]];
[sectionKeys addObject:#"Section1"];
self.tableData = resultDic;
self.sectionsTitle = resultArray;
[myTable reloadData];
My table:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return sectionKeys.count;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [sectionKeys objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int rowCount;
if(self.isFiltered)
rowCount = [[filteredTableData objectForKey:[sectionsTitle objectAtIndex:section]] count];
else
rowCount = [[tableData objectForKey:[sectionsTitle objectAtIndex:section]] count];
return rowCount;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
if(isFiltered){
NSDictionary *dict = [[filteredTableData objectForKey:[sectionsTitle objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%#", [dict objectForKey:#"Name"]];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", [dict objectForKey:#"Address"]];
}
else{
NSDictionary *dict = [[tableData objectForKey:[sectionsTitle objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%#", [dict objectForKey:#"Name"]];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", [dict objectForKey:#"Address"]];
}
return cell;
}
My search:
#pragma mark - SearchBar Delegate -
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)text{
if(text.length == 0)
{
isFiltered = FALSE;
NSLog(#"false");
}
else
{
isFiltered = true;
NSLog(#"true");
filteredTableData = [[NSMutableDictionary alloc] init];
for (MyAnnotation* ann in tableData)
{
NSRange nameRange = [ann.title rangeOfString:text options:NSCaseInsensitiveSearch];
NSRange descriptionRange = [ann.description rangeOfString:text options:NSCaseInsensitiveSearch];
if(nameRange.location != NSNotFound || descriptionRange.location != NSNotFound)
{
[filteredTableData addObject:ann];
//error
}
}
}
[myTable reloadData];
}
First of all, you need to create a state/flag for the controller/data source, in order for it to know weather you are in search/filter mode.
Then, if you are in search mode, point the data source methods to the filteredArray.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
int numberOfSections = 0;
if (_searchMode)
{
numberOfSections = self.filteredDataDict.allKeys.count;
}
else
{
numberOfSections = self.tableData.allKeys.count;
}
return numberOfSections;
}
Hope it's understood.

Resources