IOS: [self.tableView reloadData] doestn't reload the data - ios

I am studying IOS by some tutorial.After I input some text in searchBar and click search, it send Http Request and parse the JSON data ,then display in tableView, But when I input some text in searchBar then click search ,the tableView show nothing .while I type anything again in searchBar,the tableView content display.
My question is ,How can I show the content when the first time I click search but not type anything again? Thank you~~
Here is my code :
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[searchBar resignFirstResponder];
searchResults = [NSMutableArray arrayWithCapacity:10];
isLoading =YES;
[self.tableView reloadData];
NSURL *url = [self urlWithSearchText: _searchBar.text];
NSString *jsonString = [self performStoreRequestwithUrl:url];
NSDictionary *dictionary = [self parseJSON: jsonString];
[self parseDictionary : dictionary];
[searchResults sortUsingSelector:#selector(compareName:)];
isLoading = NO;
[self.tableView reloadData];
}
- (NSInteger ) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (isLoading) {
return 1;
}else if (searchResults == nil) {
return 0;
}else if([searchResults count] == 0 ){
return 1;
}else{
return [searchResults count];
}
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if (isLoading) {
return [self.tableView dequeueReusableCellWithIdentifier:LoadingCellIdentifier];
}
ResultCell *resultCell =(ResultCell *)[self.tableView
dequeueReusableCellWithIdentifier: #"ResultCell"];
UIImage *image = [UIImage imageNamed:#"TableCellGradient.png"];
UIImageView *backGroundView = [[UIImageView alloc] initWithImage: image];
UIImageView *selectedBackView = [[UIImageView alloc]initWithImage:
[UIImage imageNamed:#"SelectedTableCellGradient.png"]];
resultCell.backgroundView = backGroundView;
resultCell.selectedBackgroundView = selectedBackView;
if ([searchResults count]== 0) {
resultCell.nameLabel.text = #"Nothing Found";
resultCell.artistLabel.text = #"";
}else{
SearchResult * result = [searchResults objectAtIndex: indexPath.row];
resultCell.nameLabel.text = result.name;
NSString *kind = [self kindForDisplay:result.kind];
resultCell.artistLabel.text = [NSString stringWithFormat:#"%# (%#)",result.artistName,
kind];
}
return resultCell;
}

Related

Buggy swipe to delete display on one more row after each delete

I'm having a weird issue on UITableView delete action since iOS 11.
Here's the relevant TableView code :
#implementation ChatMessageListViewController(TableView)
#pragma mark - table view datasource/delegate
- (NSArray<UITableViewRowAction *> *) tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(nonnull NSIndexPath *)indexPath{
NSMutableArray *rowActions = [NSMutableArray array];
UITableViewRowAction *delete = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:#"Delete" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
[self deleteMessageAtIndexPath:indexPath];
}];
delete.backgroundColor = [UIColor redColor];
[rowActions addObject:delete];
return [rowActions copy];
}
- (void) deleteMessageAtIndexPath:(NSIndexPath *)indexPath {
NSString *threadID = [[self.messageArray objectAtIndex:indexPath.row] objectForKey:#"threadID"];
[self.tableView beginUpdates];
[self.messageArray removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
#weakify(self);
[UIUtil showLoadingHudWithText:WELocalString(#"message_remove_thread_loading_text", #"Deleting...", #"删除中...")];
[[AsyncUtil sharedInstance] dispatch_background_network:^{
DBManager *db = [[DBManager alloc] init];
[db deletetableData:[NSString stringWithFormat:#"singleChat WHERE threadID = '%#' ",threadID] ];
[[MemChatThreadMessages sharedInstance] removeThread:threadID];
NSDictionary * result = [Network deleteChatThread:threadID forEmail:[WEUtil getEmail]];
[[AsyncUtil sharedInstance] dispatch_main:^{
[UIUtil hideLoadingHuds];
#strongify(self);
if(self == nil) return ;
if([result[#"result"] isEqualToString:#"success"]){
}else{
[UIUtil showErrorMessage:WELocalString(#"message_remove_thread_error", #"Cannot delete this thread", #"不能删除该会话!")];
}
[self.tableView reloadData];
}];
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.messageArray count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *messageInfo = [self.messageArray objectAtIndex:indexPath.row];
if ([(NSString *)[messageInfo objectForKey:#"isAnnouncement"] isEqualToString:#"1"]) {
return 80;
}else if ([[messageInfo objectForKey:#"chatTag"] isValidString]){
return 80;
}else if([self isSpecialMessage:messageInfo]){
return 80;
}else{
return 67;
}
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"message";
if(self.events == nil){
NSDictionary * d = [WEUtil getMyEventListCache];
self.events = [[NSMutableDictionary alloc] init];
for(NSDictionary * eventSummary in d[#"events"]){
NSString * eventID = eventSummary[#"eventid"];
[self.events setObject:eventSummary forKey:eventID];
}
}
UserMessageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[UserMessageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
if(indexPath.row >= [self.messageArray count]){
TERMINATE_WITH_NIL_CELL;
}
NSDictionary *messageInfo = [self.messageArray objectAtIndex:indexPath.row];
if(![self isSpecialMessage:messageInfo]){
[cell configureCellWithMessageDict:messageInfo];
}else{
[cell configureCellWithNewMessageDict:messageInfo withEvents:self.events];
}
return cell;
}
#pragma mark - Navigation
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *msgThreadDict = [self.messageArray objectAtIndex:indexPath.row];
if(![self isSpecialMessage:msgThreadDict]){
[self tableView:tableView didSelectNormalRowAtIndexPath:indexPath];
}else{
NSString * event = msgThreadDict[#"event"];
if([event isValidString]){
if([event isEqualToString:#"no_event_messages"]){
[UIUtil showErrorMessage:#"no event id"];
}else{
[BackendTracking trackingWithAction:#"open_special" withLabel:#"threads_list"];
SpecialTopicListViewController * special = [[SpecialTopicListViewController alloc] init];
special.tracking_src = #"tab";
[self.navigationController pushViewController:special animated:YES];
}
}
}
}
-(void) tableView:(UITableView *)tableView didSelectNormalRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *msgThreadDict = [self.messageArray objectAtIndex:indexPath.row];
NSString *threadID = [msgThreadDict objectForKey:#"threadID"];
NSString *jid = [msgThreadDict objectForKey:#"jid"];
[GATracking trackCategory:#"message" withAction:#"thread_list_item_click" withLabel:threadID];
[[MemChatThreadMessages sharedInstance] setCurrentThreadID:threadID];
PrivateMessageViewController * chatVC = [[PrivateMessageViewController alloc] init];
chatVC.threadID = threadID;
chatVC.targetJID = jid;
chatVC.targetName = [msgThreadDict objectForKey:#"name"];
chatVC.unreadMsgNumber = [[self.messageArray objectAtIndex:indexPath.row][#"unreadCnt"] integerValue];
if ([(NSString *)[msgThreadDict objectForKey:#"isGroup"] isEqualToString:#"1"]) {
chatVC.isGroup = YES;
}else{
chatVC.isGroup = NO;
}
chatVC.src = #"list";
WELogInfo(#"click message");
[self.navigationController pushViewController:chatVC animated:YES];
}
#end
With the update and the changes using those trailing swipe actions there is another View appended before each time I delete an entry (until it doesn't work anymore). I've tried disabling the full trail or implementing iOS 11 trailingSwipeActionsConfigurationForRowAtIndexPath but I can't resolve this issue so far.
Do you see something wrong in the code? The main controller code is in another file.
Try reloading after you delete, after this line
[self.tableView endUpdates];
I think you removed the data from messageArray but as you are not reloading just after that so table view count is still 2 and you are reloading inside the block which might be taking time.
And one more thing you already removing data from messageArray, and then removing from db, So if you fail to remove it from db you are showing its not removed but for user it will be removed, as its no longer in message array

How to implement autocomplete for multiple textfield on certain number of text length

There is many library available for this case, but my scenario is a bit different. I have a ViewController having three textfields. I have to implement autocomplete for every textfields, and show the suggestion below the textfield. For all the datasource of textfield,I am dependent on the web-service. The problem is its working only for one textfield. Please suggest some effecient way to do this.
1)Suggestions should be shown below or above the textfield, after entering two characters. UI shouldn't be blocked, user can continue typing.(I am making call on the server with two character on background thread, and receive the response to show as suggestions. Filter logic is implemented on the server)
2) If user doesn't select anything from the suggestion, textfield data will be send to the server.
3) Anywhere tap on the screen should hide the suggestion.(The problem is, if I use tap gesture recognizer, tableview cell also doesn't get touch)
creating tableview to show suggestions
- (void)viewDidLoad {
[super viewDidLoad];
self.orderNoTextField.delegate = self;
self.empNameTextField.delegate = self;
self.custNameTextField.delegate = self;
rectForEmp = CGRectMake(0, self.empNameTextField.frame.origin.y + self.empNameTextField.frame.size.height, self.empNameTextField.frame.size.width, 120);
rectForCust = CGRectMake(0, self.orderNoTextField.frame.origin.y, self.custNameTextField.frame.size.width, 120);
autocompleteTableView = [[UITableView alloc] initWithFrame:rectForCust style:UITableViewStylePlain];
autocompleteTableView.backgroundColor = [UIColor clearColor];
autocompleteTableView.delegate = self;
autocompleteTableView.dataSource = self;
autocompleteTableView.scrollEnabled = YES;
autocompleteTableView.hidden = YES;
autocompleteTableView.canCancelContentTouches = NO;
autocompEmpTableView = [[UITableView alloc] initWithFrame:rectForEmp style:UITableViewStylePlain];
autocompEmpTableView.backgroundColor = [UIColor clearColor];
autocompEmpTableView.delegate = self;
autocompEmpTableView.dataSource = self;
autocompEmpTableView.scrollEnabled = YES;
autocompEmpTableView.hidden = YES;
autocompEmpTableView.canCancelContentTouches = NO;
[self.view addSubview:autocompleteTableView];
[self.view addSubview:autocompEmpTableView];
}
fetching suggestions
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (self.custNameTextField.text.length == 2)
{
autocompEmpTableView.hidden = YES;
[self generateDataForCustomerName];
}
else if (self.empNameTextField.text.length == 2)
{
autocompleteTableView.hidden = YES;
[self generateDataForEmployeeName];
}
return YES;
}
- (void)generateDataForCustomerName
{
/** get background thread for datasource of autocomplete **/
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
{
httpClient = [[KKHttpClient alloc]init];
//httpClient.responseDelegate = self;
//NSString *params = [self.empNameTextField text];
params = [NSString stringWithFormat:#"{\"rqBody\":{\"searchKey\":\"%#\"}}",[self.custNameTextField text]];
relativeUrl = [NSString stringWithFormat:#"auth/getcustomernamelist"];
[httpClient connectWithUrl:relativeUrl withData:params completion:^(NSMutableDictionary *responseJson)
{
NSLog(#"response check for new methods:%#", responseJson);
dispatch_async(dispatch_get_main_queue(), ^{
//Here returns to main thread to update the UI.
/** initialize the array and add object to it**/
custNameData = [[NSMutableArray alloc]init];
custNameData = [responseJson[#"rsBody"]valueForKey:#"msg"];
autocompleteTableView.hidden = NO;
[autocompleteTableView reloadData];
});
}];
}
});
}
Tableview to show suggesyions
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
if(tableView == autocompleteTableView)
{
return empNameData.count;
}
else
{
return custNameData.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == autocompEmpTableView) {
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = #"AutoCompEmpRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier];
}
employeeName = [[empNameData valueForKey:#"employeeName"]objectAtIndex:indexPath.row];
employeeId = [[empNameData valueForKey:#"employeeId"]objectAtIndex:indexPath.row];
NSString *autoCompleteText = [NSString stringWithFormat:#"%# %#%#%#", employeeName, #"(", employeeId, #")"];
cell.textLabel.text = autoCompleteText;
return cell;
}
else
{
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = #"AutoCompleteRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier];
}
customerName = [[custNameData valueForKey:#"customerName"]objectAtIndex:indexPath.row];
customerCode = [[custNameData valueForKey:#"customerCode"]objectAtIndex:indexPath.row];
NSString *autoCompleteText = [NSString stringWithFormat:#"%# %# %#%#", customerName, #"(", customerCode, #")"];
cell.textLabel.text = autoCompleteText;
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *title = selectedCell.textLabel.text;
if(tableView == autocompEmpTableView)
{
self.empNameTextField.text = title;
autocompEmpTableView.hidden = YES;
}
else{
self.custNameTextField.text = title;
autocompleteTableView.hidden =YES;
}
}

Updating UITableView while UISearchBar is active

I am writing an iOS chat application wherein I have to show the users list with a search bar. I am getting the updated user list from the server after every 2 min.
The problem that I am facing is
Case:1
If I have the search bar active and I call reload table when the datasource is updated, now if I cancel the search, I do not get my original table. Only the filtered results are shown.
Case: 2
If I have the search bar active and I just update the data source and do not reload the table, now if I cancel the search, it loops to cellforrowatindexpath as many times as there are elements in the new datasource but it does not show the updated elements. Infact, it jumbles up the elements because it considers the new index paths but uses the old data.
By jumbled up I mean,
Say if the old datasource is a1, a2, a3 and a4 with avatar images a1, a2, a3, a4.
The new datasource is a5, a1, a2, a3, a4 with images a5, a1, a2, a3, a4.
So the jumbled view that I get is
a1 with a5 image,
a2 with a1 image,
a3 with a4 image
a4 with no image.
4 cells instead of 5.
Case: 3 (working correctly)
If I have the search bar active and I do not even update the data source, nothing happens when I cancel the search (as expected). I have to reload the table to get the updated view.
What I want is that it should update the table even if search is active and when I cancel the search I should get the updated table view. I know this can be achieved by reload table when cancel button is clicked but I am trying to find an elegant solution to this.
Also, please tell me the concept (the inner workings) behind why is this working like this.
My code:
- (void)refreshUserList
{
if(dtclass.updatedUserList && [resultsArray count] ==0)
{
userArray = dtclass.getUpdatedUserList;
[self.tableView reloadData];
[dtclass setUpdatedUserList:NO];
}
else if(dtclass.updatedUserList && [resultsArray count] !=0)
{
//Uncomment for Case:1
/*userArray = dtclass.getUpdatedUserList;
[dtclass setUpdatedUserList:NO];
[self.tableView reloadData];*/
//Uncomment for Case:2
/*userArray = dtclass.getUpdatedUserList;
[dtclass setUpdatedUserList:NO];*/
//remove else if code for Case:3
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
if (resultsArray.count != 0)
{
return [resultsArray count];
}
return userArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView setSeparatorInset:UIEdgeInsetsMake(0, 70, 0, 0)];
GlobalListTableViewCell *cell = (GlobalListTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"GlobalListCell"];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"GlobalListTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
//custome class User
User *currentUser;
if(resultsArray.count !=0)
{
currentUser = [resultsArray objectAtIndex:indexPath.row];
}
else
{
currentUser = [userArray objectAtIndex:indexPath.row];
}
cell.nameLabel.text = currentUser.getName;
cell.timeLabel.text = #"5 pm";
dispatch_async(fetchImage, ^{
if([[currentUser getAvatarUrl] length]!=0)
{
[self loadImagesWithURL:[NSString stringWithFormat:#"%#%#",#"http:",[currentUser getAvatarUrl]] IndexPath:indexPath];
}
});
cell.avatarImage.image = [UIImage imageNamed:#"defaultUser.png"];
cell.messageLabel.text = #"No message";
return cell;
}
-(void) loadImagesWithURL:(NSString *)imageURL IndexPath:(NSIndexPath *)indexPath
{
NSURL *url = [NSURL URLWithString:imageURL];
NSData *data = [[NSData alloc ] initWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
GlobalListTableViewCell *cell = (GlobalListTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
cell.avatarImage.image = img;
});
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath
{
return 60;
}
- (void)filterContentForSearchText:(NSString*)searchText scope: (NSString*)scope
{
resultsArray = [[NSArray alloc] init];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF.getName contains[c] %#", searchText];
resultsArray = [userArray filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope: [[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex: [self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *) aSearchBar {
aSearchBar.text = nil;
}
Try this code for search ..
- (void)filterContentForSearchText:(NSString*)searchText
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.getName contains[c] %#",searchText];
_filteredGarages = [NSMutableArray arrayWithArray:[_allGarages filteredArrayUsingPredicate:predicate]];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[_filteredGarages removeAllObjects];
if([searchText length] != 0) {
[self filterContentForSearchText:searchText];
}
[self.tableView reloadData];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
isSearching = NO;
[self.tableView reloadData];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
if([searchBar.text isEqualToString:#""])
isSearching = NO;
else isSearching = YES;
[self.tableView reloadData];
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
if([searchBar.text isEqualToString:#""])
isSearching = NO;
else isSearching = YES;
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
resultsArray = [[NSMutableArray alloc] init];
isSearching = NO;
userArray = [[NSMutableArray alloc] init];
userArray = [//GetYourData//];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [resultsArray count];
} else {
return [userArray count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Do you table view cell job here ...
if (tableView == self.searchDisplayController.searchResultsTableView) {
isSearching = YES;
//fill the cell using resultsArray
} else {
//fill the cell using userArray
}
}

Select All,Deselect All and select particular cell in custom table view

I have created a drop-down using table cell,where i am showing my data. My data is get display in drop down.Now I want all the cell should be selected initially. Also I want to deselect all cell, and individual cell.
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([tableView isEqual:expansionTableView]) {
forState:UIControlStateNormal];
if (indexPath.row == 0) {
if ([indexPath isEqual:self.selectIndex]) {
self.isOpen = NO;
[self didSelectCellRowFirstDo:NO nextDo:NO];
self.selectIndex = nil;
}else
{
if (!self.selectIndex) {
self.selectIndex = indexPath;
[self didSelectCellRowFirstDo:YES nextDo:NO];
}else
{
[self didSelectCellRowFirstDo:NO nextDo:YES];
}
}
}else
{
objectForKey:#"surveyName"];
NSMutableArray *list=[[NSMutableArray alloc]init];
NSMutableArray *idlist =[[NSMutableArray alloc]init];
for (int i=0; i<_arraySurveyName.count; i++) {
NSMutableDictionary *dict=[_arraySurveyName objectAtIndex:i];
NSString *surveyName=[dict valueForKey:#"SurveyName"];
NSString *surveyID =[dict valueForKey:#"SurveyId"];
[list addObject:surveyName];
[idlist addObject:surveyID];
}
NSString *item = [list objectAtIndex:indexPath.row-1];
NSNumber *item1= [idlist objectAtIndex:indexPath.row-1];
str = item1;
NSLog(#"%#",str);
[_btn_surveyName setTitle:item forState:UIControlStateNormal];
[expansionTableView setHidden:YES];
}
}
else if ([tableView isEqual:expansionTableViewQtn]){
NSString *selectedQuestion=[arrayOfQuestionDetail objectAtIndex:indexPath.section];
[expansionTableViewQtn setHidden:YES];
[_btn_showQuestn setTitle:selectedQuestion forState:UIControlStateNormal];
}
}
it's my code for "didSelect".How to do this.
You can use below methods to select and deselect the cells
- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;
- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
[tableView deselectRowAtIndexPath:indexPath animated:NO];//For deselecting
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];//For selecting

UISearchBar misses elements in the non-visible part of the tableView

I have a TableView with many rows, most are not visible at the time of loading viewController. The rows of UITableView are extracted from a SQLite database. How can I make do that the SearchBar search between all rows and not just the visible ones?
In header file:
#interface ExhibitorsViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate>{
BOOL isSearchOn;
BOOL canSelectRow;
NSMutableArray * listOfExpositors;
NSMutableArray * searchResult;
}
//....
#end
In implementation file
-(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if(isSearchOn){
return [searchResult count];
//In this array there are the elements after use of searchBar
}else{
int number=[self.mutableArray count];
//In this array there are all elements of database, extracts in viewDidLoad()
return number;
}
}
- (UITableViewCell *)tableView:(UITableView *)aTableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] ;
}
if(isSearchOn){
NSString * cellValue = [searchResult objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
}else{
//loading data from the database
Database *currow =[self.mutableArray objectAtIndex:indexPath.row];
cell.textLabel.text = currow.name;
[listOfExpositors addObject:cell.textLabel.text];
//here only loads the list of names visible and not the entire table
//How do I put all the elements in this array?
NSLog(#" %#", listOfExpositors);
isSearchOn = NO;
canSelectRow = YES;
}
}
-(void) doneSearching{
isSearchOn = NO;
canSelectRow = YES;
self.tableView.scrollEnabled = YES;
[self.searchBar resignFirstResponder];
[self.tableView reloadData];
}
-(void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
isSearchOn = YES;
if(self.searchBar.text.length>0){
canSelectRow=YES;
self.tableView.scrollEnabled = YES;
}else{
canSelectRow= NO;
self.tableView.scrollEnabled = NO;
}
}
-(void) searchExpositorsTableView{
[searchResult removeAllObjects];
for (NSString *str in listOfExpositors){
NSRange titleResultsRange = [str rangeOfString:self.searchBar.text options:
NSCaseInsensitiveSearch];;
if (titleResultsRange.length >0) {
[searchResult addObject:str];
}
}
NSLog(#"%#", searchResult);
}
-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if([searchText length]>0){
canSelectRow = YES;
self.tableView.scrollEnabled = YES;
[self searchExpositorsTableView];
}else{
canSelectRow = NO;
self.tableView.scrollEnabled = NO;
}
[self.tableView reloadData];
}
-(void) searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[self searchExpositorsTableView];
[self.searchBar resignFirstResponder];
}
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if(canSelectRow){
return indexPath;
}else{
return nil;
}
NSLog(#"%d", indexPath.row);
}
It was wrong to use the array created in cellForRowAtIndexPath because it was limited only to the visible elements. I then used the NSMutableArray created in viewDidLoad () that does contain all the elements of the database. I changed the following methods:
- (UITableViewCell *)tableView:(UITableView *)aTableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//....
if(isSearchOn){
NSString * cellValue = [searchResult objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
}else{
Database *currow =[self.mutableArray objectAtIndex:indexPath.row];
cell.textLabel.text = currow.name;
//Should be removed this array and used to another, self.mutableArray
//[listOfExpositors addObject:cell.textLabel.text];
// NSLog(#" %#", listOfExpositors);
isSearchOn = NO;
canSelectRow = YES;
}
}
Method for research
-(void) searchExpositorsTableView{
[searchResult removeAllObjects];
for (Database *currow in self.mutableArray){
/*In self.mutableArray there are all elements because is created in
viewDidLoad*/
NSLog(#"list of expositors %#", self.mutableArray);
NSRange titleResultsRange = [currow.name rangeOfString:self.searchBar.text options: NSCaseInsensitiveSearch];
if (titleResultsRange.length >0) {
[searchResult addObject:currow.name];
}
}
NSLog(#"%#", searchResult);
}

Resources