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;
}
Related
I have implemented a TableView with custom cells with two labels to populate city name and city id (I kept the city id label hidden). Here my problem is when I search for the city name I cannot get the city id also, when I search the city name, I want both the values to be filtered.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellidentifier=#"citylocation";
searchTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellidentifier];
if (!cell) {
cell= [[searchTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier];
}
if(!isFilltered)
{
cell.textLabel.text = [avahotel objectAtIndex:indexPath.row];
cell.city.text = [[createdDate objectAtIndex:indexPath.row]stringValue];
}else
{
cell.textLabel.text = [filteredString objectAtIndex:indexPath.row];
}
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(isFilltered)
{
return [filteredString count];
}
return [avahotel count];
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if(searchText.length == 0)
{
isFilltered = NO;
}else
{
isFilltered = YES;
filteredString = [[NSMutableArray alloc]init];
for(NSString *str in avahotel)
{
NSRange stringRange = [str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(stringRange.location != NSNotFound)
{
[filteredString addObject:str];
}
}
}
[_searchtableview reloadData];
}
Use following code in else part for this method. searchBar textDidChange
Updated
isFilltered = YES;
filteredString = [[NSMutableArray alloc]init];
filteredCityId = [[NSMutableArray alloc]init];
for(Int i=0; i<avahotel.count; i++)
{
NSString *str = [avahotel objectAtIndex:i];
NSRange stringRange = [str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(stringRange.location != NSNotFound)
{
[filteredString addObject:[avahotel objectAtIndex:i]];
NSString *strId = [NSString stringWithFormat:#"%d",i];
[filteredCityId addObject:strId]
// here your both filter array declare.filteredcityId and filteredString
}
}
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
I have the following search setup in my app:
- (UISearchBar*)searchBar
{
if (!_searchBar) {
_searchBar = [[UISearchBar alloc] init];
_searchBar.delegate = self;
_searchBar.placeholder = kSearchBarPlaceHolder;
}
return _searchBar;
}
- (UISearchDisplayController*)searchBarDisplayContr
{
if (!_searchBarDisplayContr) {
_searchBarDisplayContr = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
_searchBarDisplayContr.delegate = self;
_searchBarDisplayContr.searchResultsDataSource = self.tableView.dataSource;
_searchBarDisplayContr.searchResultsDelegate = self.tableView.delegate;
_searchBarDisplayContr.searchResultsTableView.backgroundColor = [UIColor clearColor];
_searchBarDisplayContr.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
return _searchBarDisplayContr;
}
- (NSMutableArray *)searchResults
{
if (!_searchResults) {
_searchResults = [NSMutableArray arrayWithCapacity:_restaurants.count];
}
return _searchResults;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.searchResults removeAllObjects];
[self.restaurants enumerateObjectsUsingBlock:^(Restaurant *restaurant, NSUInteger idx, BOOL *stop) {
if ([scope isEqualToString:#"All"] || [restaurant.name isEqualToString:scope]) {
NSRange range = [restaurant.name rangeOfString:searchText
options:(NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch)];
if (range.length > 0) {
[self.searchResults addObject:restaurant];
}
}
}];
}
- (BOOL)searchDisplayController:(UISearchDisplayController*)controller shouldReloadTableForSearchString:(NSString*)searchString
{
[self filterContentForSearchText:searchString
scope:#"All"];
dispatch_async(dispatch_get_main_queue(), ^(void) {
for (UIView *v in controller.searchResultsTableView.subviews) {
if ([v isKindOfClass:[UILabel class]]) {
((UILabel *)v).text = kSearchResultsTableViewNoResultsLabel;
((UILabel *)v).font = [UIFont mediumFontOfSize:20.0f];
((UILabel *)v).textColor = [UIColor blackColor];
break;
}
}
});
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController*)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterContentForSearchText:[self.searchBarDisplayContr.searchBar text]
scope:#"All"];
return YES;
}
But for some reason when I search the searchResultsTableView is not updated / cellForRowAtIndexPath is not called. The tableView delegates and DataSource is setup in my storyboard.
Any ideas why this is happening?
UPDATE:
[self.tableView registerClass:[RestaurantsCell class] forCellReuseIdentifier:cellIdentifier];
[self.searchBarDisplayContr.searchResultsTableView registerClass:[RestaurantsCell class] forCellReuseIdentifier:cellIdentifier];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchBarDisplayContr.searchResultsTableView) {
return [self.searchResults count];
} else {
return [self.restaurants count];
}
return 0;
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
RestaurantsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
Restaurant *restaurant;
if (tableView == self.searchBarDisplayContr.searchResultsTableView) {
if (self.searchResults.count > 0) {
restaurant = self.searchResults[indexPath.row];
}
} else {
if (self.restaurants.count > 0) {
restaurant = self.restaurants[indexPath.row];
}
}
if (restaurant) {
cell.titleLabel.text = restaurant.name;
}
return cell;
}
This is the offending line:
RestaurantsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
Should be:
RestaurantsCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
Explanation:
If the tableView turns out to be your search results table view, then trying to dequeue a cell with an identifier won't work because it doesn't have prototype cells. Therefore, you have to use self.tableView
Also, your code can be cleaned up a lot:
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return (tableView == self.tableView) ? self.restaurants.count : self.searchResults.count;
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
RestaurantsCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
Restaurant *restaurant = (tableView == self.tableView) ? self.restaurants[indexPath.row] ? self.searchResults[indexPath.row];
}
cell.titleLabel.text = restaurant.name;
return cell;
}
Edit
Check out this example
I've read many questions and tried the solutions but I still couldn't resolve the problem with my tableview.
After scrolling, the data in the rows of the tableview got interchanged and sometimes missing.
Here's my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *modifierCheckCell = #"BGMModifierCheckCell";
BGMModifierCheckCell *cell = nil;
cell = (BGMModifierCheckCell *)[tableView dequeueReusableCellWithIdentifier:modifierCheckCell];
if (cell == nil) {
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:modifierCheckCell owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (BGMModifierCheckCell *)currentObject;
break;
}
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSArray *optionIds = [[[arrayInsideDict objectAtIndex:indexPath.section] objectForKey:#"optnItem"] objectAtIndex:indexPath.row];
BGMOptnCats *optnCat = [BGMOptnCats MR_findFirstByAttribute:#"iOptnCatId" withValue:[[arrayInsideDict objectAtIndex:indexPath.section] objectForKey:#"optnCatId"]];
[optionIds enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
__block int optnTag = [obj intValue];
BGMItemDayOptns *item = [BGMItemDayOptns MR_findFirstByAttribute:#"iItemDayOptnId" withValue:obj];
[item.optns.optnLangs enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
BGMOptnLangs *lang = (BGMOptnLangs *)obj;
if ([lang.sLangCode isEqualToString:#"en"]) {
NSString *optn = [NSString stringWithFormat:#"%#", lang.sOptnName];
if ([optnCat.sOptnType isEqualToString:#"single"]) {
RadioButton *rb1 = [[RadioButton alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
[rb1 setGroupID:indexPath.section AndID:optnTag AndTitle:optn];
rb1.delegate = self;
if (idx == 0) {
[cell.firstOption addSubview:rb1];
} else if (idx == 1) {
[cell.secondOption addSubview:rb1];
} else if (idx == 2) {
[cell.thirdOption addSubview:rb1];
}
} else if ([optnCat.sOptnType isEqualToString:#"multiple"]) {
SSCheckBoxView *checkBox = [[SSCheckBoxView alloc] initWithFrame:CGRectMake(0, 0, 200, 40) style:kSSCheckBoxViewStyleMono checked:NO];
checkBox.tag = optnTag;
[checkBox setStateChangedTarget:self selector:#selector(checkBoxViewChangedState:)];
[checkBox setText:#""];
[checkBox setText:optn];
if (idx == 0) {
[cell.firstOption addSubview:checkBox];
} else if (idx == 1) {
[cell.secondOption addSubview:checkBox];
} else if (idx == 2) {
[cell.thirdOption addSubview:checkBox];
}
}
}
}];
}];
}
return cell;
}
The problem is that your cells are being reused. So the rows are interchanged when scrolling.
Set the cell content outside of the if (cell == nil).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *modifierCheckCell = #"BGMModifierCheckCell";
BGMModifierCheckCell *cell = nil;
cell = (BGMModifierCheckCell *)[tableView dequeueReusableCellWithIdentifier:modifierCheckCell];
if (cell == nil) {
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:modifierCheckCell owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (BGMModifierCheckCell *)currentObject;
break;
}
}
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSArray *optionIds = [[[arrayInsideDict objectAtIndex:indexPath.section] objectForKey:#"optnItem"] objectAtIndex:indexPath.row];
BGMOptnCats *optnCat = [BGMOptnCats MR_findFirstByAttribute:#"iOptnCatId" withValue:[[arrayInsideDict objectAtIndex:indexPath.section] objectForKey:#"optnCatId"]];
[optionIds enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
__block int optnTag = [obj intValue];
BGMItemDayOptns *item = [BGMItemDayOptns MR_findFirstByAttribute:#"iItemDayOptnId" withValue:obj];
[item.optns.optnLangs enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
BGMOptnLangs *lang = (BGMOptnLangs *)obj;
if ([lang.sLangCode isEqualToString:#"en"]) {
NSString *optn = [NSString stringWithFormat:#"%#", lang.sOptnName];
if ([optnCat.sOptnType isEqualToString:#"single"]) {
RadioButton *rb1 = [[RadioButton alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
[rb1 setGroupID:indexPath.section AndID:optnTag AndTitle:optn];
rb1.delegate = self;
if (idx == 0) {
[cell.firstOption addSubview:rb1];
} else if (idx == 1) {
[cell.secondOption addSubview:rb1];
} else if (idx == 2) {
[cell.thirdOption addSubview:rb1];
}
} else if ([optnCat.sOptnType isEqualToString:#"multiple"]) {
SSCheckBoxView *checkBox = [[SSCheckBoxView alloc] initWithFrame:CGRectMake(0, 0, 200, 40) style:kSSCheckBoxViewStyleMono checked:NO];
checkBox.tag = optnTag;
[checkBox setStateChangedTarget:self selector:#selector(checkBoxViewChangedState:)];
[checkBox setText:#""];
[checkBox setText:optn];
if (idx == 0) {
[cell.firstOption addSubview:checkBox];
} else if (idx == 1) {
[cell.secondOption addSubview:checkBox];
} else if (idx == 2) {
[cell.thirdOption addSubview:checkBox];
}
}
}
}];
}];
return cell;
}
you need to remove your subviews because each time CellForRowAtIndexpath is called it will create a subview so before adding new subview remove the previous one
for (UIView *view in cell.contentView.subviews) {
[view removeFromSuperview];
}
I have an app with a tableview which you can add and delete items though when I tried to implement a search bar it crashes whenever I type one letter. Here is the code that I am using:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchText.length == 0) {
isFiltered = NO;
} else {
isFiltered = YES;
filteredPatients = [[NSMutableArray alloc] init];
for (Patient *patient in patients) {
NSRange patientNameRange = [patient.patientName rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (patientNameRange.location != NSNotFound) {
[filteredPatients addObject:patient];
}
}
}
[self.tableView reloadData];
}
This works fine though when you type a letter which has a patient in then it breaks at this line:
cell.textLabel.text = [filteredPatients objectAtIndex:indexPath.row];
Here is the code in context:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"cell"];
if ( nil == cell ) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
NSLog(#"indexPath.row = %d, patients.count = %d", indexPath.row, patients.count);
Patient *thisPatient = [patients objectAtIndex:indexPath.row];
if (isFiltered == YES) {
cell.textLabel.text = [filteredPatients objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", thisPatient.patientName, thisPatient.patientSurname];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.textColor = [UIColor blackColor];
if (self.editing) {
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
return cell;
}
And returns this error
-[Patient isEqualToString:]: unrecognized selector sent to instance 0x756c180
If you want any more code then ask.
Thanks in advance
You are iterating on the collection patients that seems to contain Patient instances and not NSString instances. So I would do something like :
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchText.length == 0) {
isFiltered = NO;
} else {
isFiltered = YES;
filteredPatients = [[NSMutableArray alloc] init];
for (Patient *patient in patients) {
NSRange patientNameRange = [patient.name rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (patientNameRange.location != NSNotFound) {
[filteredPatients addObject:patient];
}
}
}
[self.tableView reloadData];
}