UITableview Search Bar: filtering arrays - ios

i have a problem with using a search bar filter for my UITableView.
I'm logging Temperature data in multiple arrays:
NSMutableArray *timeArray; // Array which saves date and time
NSMutableArray *tempInside; // saves inside temp
NSMutableArray *tempOutside; // saves outside temp
NSMutableArray *timeArraySearch; // Array which saves date and time searched
NSMutableArray *tempInsideSearch; // saves inside temp searched
NSMutableArray *tempOutsideSearch; // saves outside temp searched
So to display the all the data, i have a UITableView. I use the timeArray for the cell.textlabel.text.
Right now i have trouble with getting the data filtered using the search bar. Here is my
filterContentForSearchText method:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
tempInsideSearch = [tempInside filteredArrayUsingPredicate:resultPredicate];
tempOutsideSearch = [tempOutside filteredArrayUsingPredicate:resultPredicate];
timeArraySearch = [timeArray filteredArrayUsingPredicate:resultPredicate];
}
I ran the application and got a empty array exception. Then i checked this method again and realized that its normal that the tempInsideSearch and tempOutsideSearch are empty, because they don't contain values like "06:41PM" ...
So finally here is my question:
How can i filter the temp arrays, that they fit the index with the timeArray?

Create a class with date/time, insideTemp, outsideTemp properties, store instances of it into an array, and apply the filtering on that array instead of using 3 different arrays to store informations highly tied ...

Related

How to filter dictionary values based on another dictionary key from a JSON?

I have a table with a UISearchController that searches it. The first table is populated from a JSON with a format of:
{
"items":
[
{
"title":"title1",
"url":"url1",
},
{
"title":"title2",
"url":"url2",
}
]
}
The "title" is shown as the cell's textLabel and the url is the link that opens when the cell is clicked.
When I search in the search bar a results table shows populated by the the titles that match the search criteria. My problem is these don't include the urls so nothing happens when these cells are clicked. My search criteria is as follows:
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// filter the search results
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [cd] %#", self.searchController.searchBar.text];
self.results = [[self.JSONarray valueForKey:#"title"] filteredArrayUsingPredicate:predicate];
[self.tableView reloadData];
}
I can see what I think is the problem but cannot figure out how to fix it. When searching it is only searching through the titles and populating the results array with these but I need the urls to filter based on the corresponding titles.
Any help would be really appreciated.
I'm typing this off the top of my head since I don't have all your code, but try the following:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"title contains [cd] %#", self.searchController.searchBar.text];
self.results = [self.JSONarray filteredArrayUsingPredicate:predicate];
The difference is that we're not filtering on the title elements of the JSON array first; instead, we're searching the whole array, and using title in the predicate.
After doing this, self.results should be an NSArray of NSDictionarys, each of which contains a title and url element. So you can access the URLs as appropriate to retrieve your results.

Get all dictionary values for certain keys (in an array)

I'm trying to get all the values of keys that are only in an array after filtering
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
if ([scope isEqualToString:#"Calendar"]) {
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchText];
self.searchResults = [NSMutableArray arrayWithArray:[[allsearchDictKeys filteredArrayUsingPredicate:resultPredicate] sortedArrayUsingSelector:#selector(localizedStandardCompare:)]];
}
}
How can I get an array, that has the values for the keys in self.searchResults array only, with the same indexPaths as their counterpart?
This is being passed into my UISearchResults updating tableView, so I would like this to occur prior to the update so I don't have to do much in cellForRowAtIndexPath. I know I can enumerate through them, and add those objects to another array, but my question is can I bypass that and just simply directly add them to an array?
Example:
self.searchResultsValuesArray = [searchDict valuesForKeys:self.searchResults];
I know there is no valuesForKeys but it's there for illustrative purposes.
You can use the NSDictionaryMethod objectsForKeys:notFoundMarker:
self.searchResultsValuesArray = [searchDict objectsForKeys:self.searchResults notFoundMarker:#""];

Extract row number of array when string searched using Predicate

I am not sure how to ask the question, so perhaps if I say what the issue is someone out there can help.
I have a SQL lite table which I use to populate two arrays: one of names and surnames, and the other array, which gets populated at the same time, of the ID of the person from the database.
I then display these names in a TableView. I use the Predicate method to search for someones name in the original array (called storiesArray).
However, when I select this person to display, it displays the First person in the stories Array.
I have tried getting the row where the search string is found, but this returns a very large number, even though it does find the string (using Predicates as explained).
How can I get the row number of the found string?
So, I have tried the following code:
NSUInteger indexOfTheObject = [storiesArray indexOfObject: searchText];
But this returns the number 2147483647, which in effect is a -1.
I know that the searchText is in stories array because the following code does return a valid search result:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchText];
self.searchResult = [NSMutableArray arrayWithArray:[storiesArray filteredArrayUsingPredicate:resultPredicate]];
}
self.searchResult gets populated with the correct string.
Thanks in advance.
Similar Threads here:
How retrieve an index of an NSArray using a NSPredicate?
how to find the index position of the ARRAY Where NSPredicate pick the value. I use filteredArrayUsingPredicate as filter
http://useyourloaf.com/blog/2010/10/19/searching-arrays-with-nspredicate-and-blocks.html
NSUInteger index = [self.myarray indexOfObjectPassingTest:
^(id obj, NSUInteger idx, BOOL *stop) {
return [predExists evaluateWithObject:obj];
}];

Adding a Search Bar to a Table View with Core Data

I have an app that saves data to a Core Data sql then view it in a table view.
The data model:
Entity: Fruits
Attributes: name, picture
So in the table view, cell.textLabel.text = Fruits.name
Each cell has a segue with a view that shows Fruits.picture.
I want to add a search bar to search in Fruits names.
I followed this tutorial: http://www.appcoda.com/search-bar-tutorial-ios7/
But the problem I had is in filterContentForSearchText
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
I'm using core data not an array for storing data. And I don't know how to filter it so I can display searchResults in table cells and use it in prepareForSegue.
Since you're using core data and not an array of Fruits you should filter your data this way:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Fruits" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
[fetchRequest setPredicate:predicate];
NSError *error;
NSArray* searchResults = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}
To show the picture in a second viewController you should put something like this in you prepareForSegue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
Fruit *selectedItem;
if (self.searchDisplayController.active) {
selectedItem = [searchResults objectAtIndex:indexPath.row];
} else {
selectedItem = [fruitsList objectAtIndex:indexPath.row];
}
DestinationViewController *destination = segue.destinationViewController;
destination.fruit = selectedItem;
}
Where fruitsList is an array with all the fruit objects (The one used to show the fruits without any filter), and DestinationViewController is the the controller that will show the picture.
First, why is your entity name in the plural? That is confusing. You should rename your entity Fruit.
Second, how come your variable names start with capital letters? This is again confusing because they can be mistaken for class names. You should rename your variables fruit, such as in fruit.name.
Third, you should use a NSFetchedResultsController to populate your table view. You could have a separate one just for the search or filter in memory. Both are preferable to doing a manual fetch in each call to filterContentForSearchText. Your filter code looks fine (it is the in-memory version). However, I do not see where you reload the data of your search results table view.
Fourth, the search is completely unrelated to the segue problem. Each cell should be associated with a particular Fruit instance. (Either custom cells with a #property of type Fruit, or use the fetched results controller objectAtIndexPath.) In prepareForSegue you just assign that fruit to the detail view controller (which should have an appropriate #property set up).

KVC to add values from multiple Keys to NSMutableArray

I want to display name and lastName in my UITableViewCell. I have an array with a lot of data that I retrieve from a database, and pretty much everything I need is in the array, the trick is to filter and show the results as I want.
I have the following code to filter what is being typed on searchBar and add to an NSMutableArray:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"usuario.username contains [cd] %#", searchText];
NSArray *filtroUsuario = [name filteredArrayUsingPredicate:predicate];
searchResults = [filtroUsuario valueForKeyPath:#"#distinctUnionOfObjects.usuario.nome"];
I use #distinctUnionOfObjects because the objects that I'm filtering are not user objects, therefore I want to retrieve user values, so as some objects point to the same user, I get duplicate names.
The code to put information on the UITableView is like this:
cell.textLabel.text = searchResults[indexPath.row];
It all works fine. My trouble is that now I want to show one more key on the cell, so the keypath would be usuario.sobrenome. How would I put both values together?
I've tried playing with the line:
searchResults = [filtroUsuario valueForKeyPath:#"#distinctUnionOfObjects.usuario.nome"];
and got some interesting results, but not the one I'm expecting.
It looks like you should be able to use #distinctUnionOfObjects.usuario, so your results is an array of user objects (or some other objects with the keys that you require). Then in the table view cell setup you do:
id user = searchResults[indexPath.row];
cell.textLabel.text = [user valueForKey:#"nome"];
cell.otherTextLabel.text = [user valueForKey:#"sobrenome"];

Resources