I am parsing a json to display the contents in the tableview. I have the array containing parsed json being populated in getReceivedData which is called after the UITAbleView Delegate methods. So it is problem in populating tableview as when the compiler attempts to populate it the array is not yet initialized.
- (void)getReceivedData:(NSMutableData *)data sender:(RestAPI *)sender{
NSError * error=nil;
NSArray *receivedData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSString *dictionaryKey=#"department";
NSString *predicateString=#"software";
NSPredicate *predicate=[NSPredicate predicateWithFormat:#" %K == %# ", dictionaryKey,predicateString];
NSArray *shortlisted=[receivedData filteredArrayUsingPredicate:predicate];
for(int i = 0; i<shortlisted.count; i++)
{
NSDictionary *detailItems=[shortlisted objectAtIndex:i];
NSString *name=[detailItems objectForKey:#"emp_name"];
NSString *designation=[detailItems objectForKey:#"designation"];
NSString *email=[detailItems objectForKey:#"email"];
NSString *phone_no=[detailItems objectForKey:#"phone_no"];
// NSString *image=[detailItems objectForKey:#"url_path"];
dictionary1=[NSMutableDictionary dictionaryWithObjectsAndKeys:
name, #"keyname",
designation, #"keydesignation",
email, #"keyid",
phone_no, #"keyphone",
nil];
[myObject1 addObject:dictionary1];
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section{
if(isfiltered==YES){
return [filteredArray count];
}
else{
return [myObject1 count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
MyTableCell *cell=[tableView dequeueReusableCellWithIdentifier:#"myCell"];
if(!cell){
[tableView registerNib:[UINib nibWithNibName:#"MyTableCell" bundle:nil]
forCellReuseIdentifier:#"myCell"];
cell=[tableView dequeueReusableCellWithIdentifier:#"myCell"];
}
if(isfiltered==NO)
{
NSDictionary * tmpdict= [myObject objectAtIndex:indexPath.row];
cell.nameLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyname"]];
cell.designationLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keydesignation"]];
cell.idLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyid"]];
cell.phoneLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyphone"]];
cell.mainImg.image = [UIImage imageNamed:[tmpdict objectForKeyedSubscript:#"keyimage"]];
}
else{
NSDictionary * tmpdict= [filteredArray objectAtIndex:indexPath.row];
cell.nameLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyname"]];
cell.designationLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keydesignation"]];
cell.idLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyid"]];
cell.phoneLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyphone"]];
cell.mainImg.image = [UIImage imageNamed:[tmpdict objectForKeyedSubscript:#"keyimage"]];
}
return cell;
}
This window was supposed to view the table
In a mutable dictionary first you have to give object then its key. You are doing wrong
for(int i = 0; i<shortlisted.count; i++)
{
NSDictionary *detailItems=[shortlisted objectAtIndex:i];
NSString *name=[detailItems objectForKey:#"emp_name"];
NSString *designation=[detailItems objectForKey:#"designation"];
NSString *email=[detailItems objectForKey:#"email"];
NSString *phone_no=[detailItems objectForKey:#"phone_no"];
dictionary1=[NSMutableDictionary dictionaryWithObjectsAndKeys:
name,#"keyname",
designation,#"keydesignation",
email,#"keyid",
phone_no,#"keyphone",
nil];
[myObject1 addObject:dictionary1];
}
Actually this is not correct way to intialize dictionary as you did, #"%#" is used %# is a placeholder in a format string for any object.
dictionary1=[NSMutableDictionary dictionaryWithObjectsAndKeys:
name,#"keyname",
designation,#"keydesignation",
email,#"keyid",
phone_no,#"keyphone",
nil];
I have UITableView with countries and their phone codes
- (NSArray *)sortedCountryLetters {
if (_sortedCountryLetters == nil) {
[self countriesInfo];
}
return _sortedCountryLetters;
}
- (NSDictionary *)countriesInfo {
if (_countriesInfo == nil) {
NSMutableArray *countries = [NSMutableArray new];
for (NSString *key in [AppDelegate phoneCodes]) {
[countries addObject:#{
#"key": key,
#"name": [_locale displayNameForKey:NSLocaleCountryCode value:key],
#"code": [AppDelegate phoneCodes][key]
}];
}
NSMutableArray *firstLetters = [NSMutableArray new];
NSMutableDictionary *result = [NSMutableDictionary new];
for (NSDictionary *country in countries) {
NSString *name = country[#"name"];
NSString *firstLetter = [[name substringToIndex:1] uppercaseString];
if ([[result allKeys] containsObject:firstLetter]) {
NSMutableArray *letterCountries = result[firstLetter];
[letterCountries addObject:country];
}
else {
result[firstLetter] = [#[country] mutableCopy];
[firstLetters addObject:firstLetter];
}
}
[firstLetters sortUsingComparator:^NSComparisonResult(NSString *letter1, NSString *letter2) {
return [letter1 compare:letter2];
}];
_sortedCountryLetters = [firstLetters copy];
for (NSString *firstLetter in [result allKeys]) {
NSMutableArray *letterCountries = result[firstLetter];
[letterCountries sortUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
NSString *name1 = obj1[#"name"];
NSString *name2 = obj2[#"name"];
return [[name1 lowercaseString] compare:[name2 lowercaseString]];
}];
}
_countriesInfo = [result copy];
}
return _countriesInfo;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[[self countriesInfo] allKeys] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *firstLetter = [self sortedCountryLetters][section];
NSArray *letterCountries = [self countriesInfo][firstLetter];
return [letterCountries count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"countryCell"];
NSString *firstLetter = [self sortedCountryLetters][indexPath.section];
NSArray *letterCountries = [self countriesInfo][firstLetter];
NSDictionary *country = letterCountries[indexPath.row];
[[cell textLabel] setText:country[#"name"]];
[[cell textLabel] setTextColor:[OmwThemes defaultColorForegroundMain]];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [self sortedCountryLetters][section];
}
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [self sortedCountryLetters];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:index] atScrollPosition:UITableViewScrollPositionTop animated:YES];
return [[self sortedCountryLetters] indexOfObject:title];
}
Section indices already shows at table view right side, but tapping do nothing.
In debug I saw that tableView:sectionForSectionIndexTitle:atIndex: method never called.
Table view is connected to datasource and delegate. I did try both plain and group table view styles.
What did I miss?
Update:
My table view look:
In my app, I'm working with UISearchBar where user will search from an NSMutableArray by searching with user name. Here is my method for searching user from NSMutableArray
- (void)searchTableList
{
NSString *searchString = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in contentList)
{
NSArray *array = [dictionary objectForKey:#"username"];
[searchArray addObject:array];
}
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchString options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[filteredContentList addObject:sTemp];
}
}
And Here is how I'm configuring UITableView for showing search results
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"SearchListTableViewCell";
NSMutableDictionary *dict=[contentList objectAtIndex:indexPath.row];
SearchListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"SearchListTableViewCell" owner:nil options:nil];
cell = (SearchListTableViewCell*)[topLevelObjects objectAtIndex:0];
cell.backgroundColor=[UIColor colorWithRed:239.0/255 green:239.0/255 blue:239.0/255 alpha:1];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
// Configure the cell...
if (isSearching)
{
cell.friendName.text = [filteredContentList objectAtIndex:indexPath.row];
NSMutableArray *searchImageArray=[[NSMutableArray alloc]init];
for (NSDictionary *dictionary in contentList)
{
NSArray *imageArray=[dictionary objectForKey:#"thumbnail_path_150_150"];
NSLog(#"image arrayt is %#",imageArray);
[searchImageArray addObject:imageArray];
}
for (NSString *imageS in searchImageArray) {
NSRange title=[imageS rangeOfString:cell.friendName.text options:NSCaseInsensitiveSearch];
if (title.length>0) {
[filteredImage addObject:imageS];
}
}
NSString *url=[NSString stringWithFormat:#"%#/get_image?avatar=%#",BaseURL,[filteredImage objectAtIndex:indexPath.row]];
url=[url stringByReplacingOccurrencesOfString:#"\\" withString:#"/"];
UIImage* myImage = [UIImage imageWithData:
[NSData dataWithContentsOfURL:
[NSURL URLWithString:url]]];
[cell.friendProfileImage setImage:myImage];
NSLog(#"filtered Image data %lu",(unsigned long)filteredImage.count);
NSLog(#"filtered content list data %lu",(unsigned long)filteredContentList.count);
}
else
{
cell.friendName.text =[dict objectForKey:#"username"];
NSString *url=[NSString stringWithFormat:#"%#/get_image?avatar=%#",BaseURL,[dict objectForKey:#"thumbnail_path_150_150"]];
url=[url stringByReplacingOccurrencesOfString:#"\\" withString:#"/"];
UIImage* myImage = [UIImage imageWithData:
[NSData dataWithContentsOfURL:
[NSURL URLWithString:url]]];
[cell.friendProfileImage setImage:myImage];
}
return cell;
}
Now I want to fetch the rest data of searched user name from NSMutableDictionary. Here is my dictionary.
(
{
jid = "hey#196.0.0.1";
"thumbnail_path_150_150" = "E\\path\\to\\getImage\\files\\heythumbnail";
username = hey;
},
{
jid = "tweety#196.0.0.1";
"thumbnail_path_150_150" = "E:\\path\\to\\getImage\\files\\tweetythumbnail";
username = tweety;
}
)
Here I want to get the image of searched user. If user searches hey, It must show "thumbnail_path_150_150"
="E\\path\\to\\getImage\\files\\heythumbnail"; this image on tableViewCell. I tried my code for setting image But it replaces image when two users have same name. Like if one user is Ray and another is Blueray , then it changes the image of both. I know i wrote too much. But I'm really confused at this point. Please anyone help solving this issue.
Apply a NSPredicate to filter your array and then use this array to populate the tableView
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"username contains[c] %#",_search_bar.text];
NSArray *filteredArray = [yourMainArray filteredArrayUsingPredicate:predicate];
NSLog(#"here is the filteredCandyArray%#",filteredCandyArray);
//set it to the array you use to fill the table
_dataSourceArray = _filteredCandyArray;
//go!
[_yourTable reloadData];
String comparisons are by default case and diacritic sensitive. You can modify an operator using the key characters c and d within square braces to specify case and diacritic insensitivity respectively, for example firstName BEGINSWITH[cd] $FIRST_NAME.
BEGINSWITH: The left-hand expression begins with the right-hand expression.
CONTAINS: The left-hand expression contains the right-hand expression.
ENDSWITH: The left-hand expression ends with the right-hand expression.
LIKE: The left hand expression equals the right-hand expression: ? and * are allowed as wildcard characters, where ? matches 1 character and * matches 0 or more characters.
MATCHES: The left hand expression equals the right hand expression .
or further details please visit http://nshipster.com/nspredicate/
Simplest way to do this is by using predicates and with a little modifications your code can go somewhat like this
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"username == %#", #"ray"];
NSArray *searchedArray = [rootArray filteredArrayUsingPredicate:predicate];
The above code will only return values where username is ray and not Ray or RAY etc
I recommend you to use Search Bar and Search Display Controller rather than Search Bar.
Also have a look at the following code, it covers everything you want.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#pragma mark
#pragma mark - View Lifecycle
-(void)viewDidLoad
{
[super viewDidLoad];
NSDictionary *dic1 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"1", #"India", #"IN", #"+91", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
NSDictionary *dic2 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"2", #"Australia", #"AU", #"+61", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
NSDictionary *dic3 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"3", #"New Zealand", #"NZ", #"+64", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
NSDictionary *dic4 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"4", #"South Africa", #"SA", #"+27", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
NSDictionary *dic5 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"5", #"England", #"EN", #"+44", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
NSDictionary *dic6 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"6", #"Israel", #"IS", #"+972", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
NSDictionary *dic7 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"7", #"Afghanistan", #"AF", #"+93", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
NSDictionary *dic8 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"8", #"Ireland", #"IR", #"+353", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
NSDictionary *dic9 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"9", #"China", #"CN", #"+86", nil] forKeys:[NSArray arrayWithObjects:#"CountryId", #"CountryName", #"CountryCode", #"ISDCode", nil]];
arrTotalCountries = [NSArray arrayWithObjects:dic1, dic2, dic3, dic4, dic5, dic6, dic7, dic8, dic9, nil];
}
#pragma mark
#pragma mark - UITableView delegate, datasource methods
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(tableView == self.searchDisplayController.searchResultsTableView){
return [arrFilteredCountries count];
}
else{
return [arrTotalCountries count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"CellIdentifier%ld%ld",(long)indexPath.section,(long)indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *dicCountry;
if (tableView == self.searchDisplayController.searchResultsTableView) {
dicCountry = [arrFilteredCountries objectAtIndex:indexPath.row];
} else {
dicCountry = [arrTotalCountries objectAtIndex:indexPath.row];
}
NSString *strShow = [NSString stringWithFormat:#"%# (%#)",[dicCountry objectForKey:#"CountryName"],[dicCountry objectForKey:#"ISDCode"]];
cell.textLabel.text = strShow;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *dicCountry;
if (tableView == self.searchDisplayController.searchResultsTableView) {
dicCountry = [arrFilteredCountries objectAtIndex:indexPath.row];
} else {
dicCountry = [arrTotalCountries objectAtIndex:indexPath.row];
}
NSString *countryName = [dicCountry objectForKey:#"CountryName"];
NSString *CountryISDCode = [dicCountry objectForKey:#"ISDCode"];
[self showAlertWithTitle:countryName message:CountryISDCode];
}
#pragma mark
#pragma mark - Other method Implementation
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(SELF.CountryName BEGINSWITH[cd] %#) OR (SELF.ISDCode CONTAINS[cd] %#)", searchText, searchText];
arrFilteredCountries = [arrTotalCountries filteredArrayUsingPredicate:predicate];
}
-(void)showAlertWithTitle:(NSString *)title message:(NSString *)message
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
#pragma mark
#pragma mark - UISearchbar controller delegate
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#pragma mark
#pragma mark - Memory management
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
Also add a comment in case, anyone stuck at some point. I have implemented this and it works nicely. It's a short and best way to add search function to your Table view.
I have created a app that fetches information from a blog and shows it in the app. After i fetch the data it is supposed to be shown on the table view. It shows the things that i have posted but the things are in alphabetical order rather than the time i posted the thing.
Here is the code
#implementation EventsTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.firstLettersArray = [NSMutableArray array];
self.eventsDictionary = [NSMutableDictionary dictionary];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self searchForEvents];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[self searchForEvents];
}
- (void)searchForEvents
{
[self.searchBar resignFirstResponder];
NSString *eventsSearchUrlString = [NSString stringWithFormat:#"https://www.googleapis.com/blogger/v3/blogs/1562818803553764290/posts?key=AIzaSyBTOxz-vPHgzIkw9k88hDKd99ILTaXTt0Y"];
NSURL *eventsSearchUrl = [NSURL URLWithString:eventsSearchUrlString];
NSURLRequest *eventsSearchUrlRequest = [NSURLRequest requestWithURL:eventsSearchUrl];
NSURLSession *sharedUrlSession = [NSURLSession sharedSession];
NSURLSessionDataTask *searchEventsTask =
[sharedUrlSession dataTaskWithRequest:eventsSearchUrlRequest completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error)
{
dispatch_async(dispatch_get_main_queue(),
^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if(error)
{
UIAlertView *searchAlertView = [[UIAlertView alloc] initWithTitle:#"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[searchAlertView show];
}
else
{
NSString *resultString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Search results: %#", resultString);
NSError *jsonParseError = nil;
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonParseError];
if(jsonParseError)
{
UIAlertView *jsonParseErrorAlert = [[UIAlertView alloc] initWithTitle:#"Error" message:jsonParseError.localizedDescription delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[jsonParseErrorAlert show];
}
else
{
for(NSString *key in jsonDictionary.keyEnumerator)
{
NSLog(#"First level key: %#", key);
}
[self.firstLettersArray removeAllObjects];
[self.eventsDictionary removeAllObjects];
NSArray *searchResultsArray = [jsonDictionary objectForKey:#"items"];
//NSLog(#"test%#",searchResultsArray);
for(NSDictionary *eventsInfoDictionary in searchResultsArray)
{
Events *event = [[Events alloc] init];
event.eventName = [eventsInfoDictionary objectForKey:#"title"];
event.eventDescription =[eventsInfoDictionary objectForKey:#"content"];
NSLog(#"Event Name : %#",event.eventName);
NSLog(#"Event Description : %#",event.eventDescription);
NSString *eventsFirstLetter = [event.eventName substringToIndex:1];
NSMutableArray *eventsWithFirstLetter = [self.eventsDictionary objectForKey:eventsFirstLetter];
if(!eventsWithFirstLetter)
{
eventsWithFirstLetter = [NSMutableArray array];
[self.firstLettersArray addObject:eventsFirstLetter];
}
[eventsWithFirstLetter addObject:event];
[self.eventsDictionary setObject:eventsWithFirstLetter forKey:eventsFirstLetter];
if ([event.eventDescription containsString:#"<br />"]) {
NSString* eventDescrip = event.eventDescription;
NSString* stringWithoutHTMLtags = [eventDescrip stringByReplacingOccurrencesOfString:#"<br />" withString:#""];
event.eventDescription = stringWithoutHTMLtags;
}
NSLog(#"Event Name : %#",event.eventName);
NSLog(#"Event Description : %#",event.eventDescription);
}
[self.firstLettersArray sortUsingSelector:#selector(compare:)];
[self.tableView reloadData];
}
}
});
}];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[searchEventsTask resume];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.firstLettersArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *firstLetter = [self.firstLettersArray objectAtIndex:section];
NSArray *eventsWithFirstLetter = [self.eventsDictionary objectForKey:firstLetter];
return eventsWithFirstLetter.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"eventTitleCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *firstLetter = [self.firstLettersArray objectAtIndex:indexPath.section];
NSArray *eventsWithFirstLetter = [self.eventsDictionary objectForKey:firstLetter];
Events *event = [eventsWithFirstLetter objectAtIndex:indexPath.row];
cell.textLabel.text = event.eventName;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/*
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
NSLog(#"Row selected %#",cellText);*/
NSString *firstLetter = [self.firstLettersArray objectAtIndex:indexPath.section];
NSArray *eventsWithFirstLetter = [self.eventsDictionary objectForKey:firstLetter];
Events *event = [eventsWithFirstLetter objectAtIndex:indexPath.row];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
DescriptionViewController *descriptionViewController = (DescriptionViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"descriptionController"];
descriptionViewController.eventNameDesc = event.eventDescription;
descriptionViewController.navigationItem.title = event.eventName;
[self.navigationController pushViewController:descriptionViewController animated:YES];
}
#end
You are trying to sort firstLettersArray which contain Events objects by using standard sort: function which doesn't know how to work with your custom objects.
You can use sortedArrayUsingComparator: function like this:
[firstLettersArray sortedArrayUsingComparator:^NSComparisonResult(Events *obj1, Events *obj2) {
// return object comparison result here
}];
Edit: Also you need to have NSDate property in Events class and feel it with event created time. I believe event created time should be contained in eventsInfoDictionary. Eventually you will be able to compare obj1 and obj2 using NSDate property.
i think this line not working
[self.firstLettersArray sortUsingSelector:#selector(compare:)];
use this line of code may help you....
sortedArray = [anArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
Now my search work by sectionsTitle, if I write "Category1" or "Category2" it find section Category1, or Category2, but I need to search by NAMES in all this sections, from here:
NSDictionary *dict = [[tableData objectForKey:[sectionsTitle objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
[NSString stringWithFormat:#"%#", [dict objectForKey:#"Name"]];
What I need to change in my code for search by Names? Now I'm confused with all that NSArray's, NSMutableArray's and NSDictionary :(
I load my data like this:
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];
sectionKeys = [NSMutableArray new];
sectionsTitle = [NSMutableArray new];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"blueKey"])
{
ann = [dict objectForKey:#"Category1"];
[resultArray addObject:#"Category1"];
[resultDic setValue:ann forKey:#"Category1"];
[sectionKeys addObject:#"Section 1"];
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"yellowKey"])
{
ann = [dict objectForKey:#"Category2"];
[resultArray addObject:#"Category2"];
[resultDic setValue:ann forKey:#"Category2"];
[sectionKeys addObject:#"Section 2"];
}
self.tableData = resultDic;
self.sectionsTitle = resultArray;
[myTable reloadData];
This is how I filter data:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [sectionsTitle filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
This is how my table look like:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView == self.searchDisplayController.searchResultsTableView) {
return 1;
}else{
return sectionKeys.count;
}
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (tableView == self.searchDisplayController.searchResultsTableView) {
return #"Search";
}else{
return [sectionKeys objectAtIndex:section];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
int num = [[tableData objectForKey:[sectionsTitle objectAtIndex:section]] count];
return num;
}
}
- (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 (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
NSDictionary *dict = [[tableData objectForKey:[sectionsTitle objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont fontWithName:#"Avenir" size: 16.0];
cell.detailTextLabel.font = [UIFont fontWithName:#"Avenir" size: 12.0];
cell.textLabel.text = [NSString stringWithFormat:#"%#", [dict objectForKey:#"Name"]];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", [dict objectForKey:#"Address"]];
}
return cell;
}
My data structure:
With a simplified data set (only the Name entry included in the dictionaries), this should reproduce your setup:
NSArray *categories = #[
#[#{#"Name":#"Joe"}, #{#"Name":#"Jane"}],
#[#{#"Name":#"Anne"}, #{#"Name":#"Bob"}]
];
Then the ANY operator of NSPredicate will find the array you are after:
NSString *nameToSearch = #"Bob";
NSPredicate *catPred = [NSPredicate predicateWithFormat:#"ANY Name = %#", nameToSearch];
To see how this predicate can filter your category array:
NSArray *filteredCats = [categories filteredArrayUsingPredicate:catPred];
BTW, you might get less confused if you build some custom objects to hold your data instead of relying only on arrays and dictionaries.