Hi in my ipad application am performing searching operation using searchbar.For performing thise searching operation i am using following logic
If any element includes the character what i am entering in search bar, those elements have to pickup from so many elements and display in table.
code:
NSRange rTextRange = [finalSearchingString rangeOfString:searchStr options:(NSCaseInsensitiveSearch)];`
if (range.location != NSNotFound){
[self.filterdList addObject:product];
}
here final results avaialble in filterdList array and that array data i will display in tableview.
Now my issue in this operation is actually now the requirement is changed. New requirement is The product which are starting with searching characters those only have to display not included products. Please help me how to implement this functionality .Thanks in advance.
try like this i Hope this one helps you,
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", txtSearch.text];
NSArray *ResultArray = [yourArray filteredArrayUsingPredicate:predicate];
[tableview reloadData];
kept above code in searchBar delegate method and reload the tableview with result array.
Related
Is it possible to remove an object from a fetchedResultsController fetchedObjects?
For example I have the following code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"pack.packName IN %#", allowedPackNames];
for (int i = 0; i < [tempFetchResults.fetchedObjects count]; i++){
Author *author = [tempFetchResults.fetchedObjects objectAtIndex:i];
NSSet *filteredQuotes = [author.quotes filteredSetUsingPredicate:predicate];
if ([filteredQuotes count] > 0){
author.quotes = filteredQuotes;
} else {
//remove this author from the fetchedObjects array
}
}
How can I do this?
To remove the object from the data store:
[self.managedObjectContext deleteObject:object];
[self.managedObjectContext save:nil];
[self.fetchedResultsController self.fetchedResultsController.fetchRequest];
[tableView reloadData];
To just remove the object from the fetched results controller array, you need to change the predicate. Make sure you disable cache (or change the cache name) for this to work.
I think you could define a property 'excluded' or something like that of integer type and incorporate that property into your fetch request predicate. Now when you mark a quote as excluded, fetched results controller will do all the heavy lifting for you without refetching and all.
Update #1
Addressing the bigger issue here I think using subquery in your fetched results controller predicate is much better idea.
Try using:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SUBQUERY(quotes, $x, $x.pack.packName IN %#).#count > 0", allowedPackNames];
as a predicate for your fetch request for fetched results controller and forget about manual filtering.
Basically what this subquery should do for you is filter out all authors that have quotes count fitting your packName criteria. I admit I did not test this query. If you say this won't work for you I will go through the trouble and test it myself.
I was following a tutorial: http://www.devx.com/wireless/Article/43374
so I could add alphabet sorting and panning to my UITableView of songs and I have finished coding but this method I have followed slows down the UITableView by filtering arrays and retrieving values in the cellForRowAtIndexPath method.
I cant figure out how I can remove the excess coding to increase the speed. All the MPMediaItems are stored in the tableTracks array. Which is initialized in viewDidLoad. And thee musicIndex is an array of the alphabets(first letter of each song). I extended MPMediaItem to include an NSString firstLetter that is the first letter of the song.
Any help speeding it up?
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//--Create Cell--\\
.........
//--Load Info--\\
NSString *alphabet = [musicIndex objectAtIndex:[indexPath section]];
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"firstLetter beginswith[c] %#", alphabet];
NSArray *songs = [tableTracks filteredArrayUsingPredicate:predicate];
//Needed Object
MPMediaItem *item = [songs objectAtIndex:indexPath.row];
//--Rest of Method--\\
...........
return cell;
}
If you are showing separate sections, one for each letter of the alphabet, I would create an array of dictionaries from my data, in viewDidLoad, not here. The dictionaries would have the first letter of the song as the key, and an array of songs as the value. That way, all the filtering and sorting is done up front, rather than in each row as the table is populated.
iCloud doesn't support ordered sets for relationships, only sets. Right now, i've made an attribute called 'entryIndex', where it stores it's own index value that it's given. When the user deletes the object at a specific index, I want to identify the object and change the value of the objects with higher indexes. How do I do this?
Assuming you have consecutive indexes and want to keep them "tight" without gaps:
NSArray *filtered = [fetchedObjects filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"entryIndex > %#",
deletedObject.entryIndex]];
for (NSManagedObject *obj in filtered) {
obj.entryIndex = [NSNumber numberWithInt:[obj.entryIndex intValue]-1];
}
[self.managedObjectContext save:nil];
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[displayItems removeAllObjects]; //clear array to ensure no repeat info
if ([searchText length] == 0) {
displayItems = (NSMutableArray *)allItems;
}
else {
//search by item category
NSPredicate *catPredicate = [NSPredicate predicateWithFormat:#"category
CONTAINS[cd] %#",searchText];
[searchable filterUsingPredicate:catPredicate];
//further search by item name
NSPredicate *namePredicate = [NSPredicate predicateWithFormat:#"name CONTAINS[cd]
%#",searchText];
[searchable filterUsingPredicate:namePredicate];
displayItems = searchable;
searchable = (NSMutableArray *)allItems;
}
[self.searchResults reloadData];
}
This method is part of a simple searchable table view I am trying to create for a larger project. My code compiles and runs, and when i type something into the search bar the search function appears to work, but then the program crashes as soon as a second letter is typed. If I type two letters in a row, it throws 'NSInvalidArgumentException', reason: '-[_NSArrayI filterUsingPredicate:]: unrecognized selector sent to instance 0x6d6c040', but if I type one letter and then hit enter or backspace, it throws this guy 'NSInvalidArgumentException', reason: '-[_NSArrayI removeAllObjects]: unrecognized selector sent to instance 0x6a7f300' when I type a second letter.
I am pretty new to objective-c, and this has me perplexed. Any help I could get would be greatly appreciated.... :-/ Still having issues since update.
"One does not simply cast NSArray into NSMutableArray and then call NSMutableArray methods on it" - Boromir
Create a mutable copy instead, like this:
searchable = [allItems mutableCopy];
NOTE: Make sure to release searchable when you are finished with it.
You have to use NSMutableArray to call the methods.
NSArray has a method "filteredArrayusingPredicate".
The simple solution is use NSMutableArray.
I have integrated the search function to my app to query core data/.sqlite and it works ok. But I have a problem and I am not sure which class configuration should I look at, could someone points me to the light, thanks
Basically my model is this
TableView 1
Display Product Category
selectRow --> TableView2
TableView 2
Display Products of selected Category
selectRow --> TableView3
As I integrated the UISearchBar in TableView 1, I wish to have the function when people search the product they want and it will show up the product's name right away in the table view. I tried, but the result is showing the Category which contains the "searched product".
So, how could I get this to show up correctly and which section of configuration should I look at?
UISearchDisplayController *searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
[self performSelector:#selector(setSearchDisplayController:) withObject:searchDisplayController];
[searchDisplayController setDelegate:self];
[searchDisplayController setSearchResultsDataSource:self];
[searchDisplayController setSearchResultsDelegate:self];
[searchDisplayController release];
[self.tableView setContentOffset:CGPointMake(0,self.searchDisplayController.searchBar.frame.size.height)];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
self.filteredListContent = [NSMutableArray arrayWithCapacity:[[[self fetchedResultsController] fetchedObjects] count]];
}
Is it this part of the code?
Thanks
Update with more info:
Configure Cell
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *entity = nil;
if (self.searchIsActive){ // Configure the cell to show the searched item's name
entity = [[self filteredListContent] objectAtIndex:[indexPath row]];
cell.textLabel.textColor = [UIColor blackColor];
} else {// Configure the cell to show the category's name
cell.textLabel.textColor = [UIColor blackColor];
entity = [fetchedResultsController objectAtIndexPath:indexPath];
}
cell.textLabel.text = [entity valueForKey:#"nameEN"];
}
The Search Predicate
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"ANY products.nameEN CONTAINS[cd] %#", searchText];
self.filteredListContent = [[[self fetchedResultsController] fetchedObjects] filteredArrayUsingPredicate:predicate];
}
The Core Data Structure
Category{
nameEN
products <- one to many relation ->> Product.productcat
}
Product{
nameEN
spec
productcat <<-- many to one relation-> Category.products
}
Thank you.
If your data model has a Product entity and a Category entity and your fetches are returning Category objects instead of Product objects, then you have the wrong entity set for your fetch.
[ignore following as it applies to a different type of search -- techzen]
You usually create a separate fetch for the search because every time the users enters new characters in the search, the predicate for the fetch must change.
Update:
Okay, I misunderstood the type of search you were implementing. You are filtering the return of an existing fetch instead of fetching based on the entered search.
Looking at the predicate and data model in your update I think it clear that the predicate will only work against an array of Category objects. This:
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"ANY products.nameEN CONTAINS[cd] %#", searchText];
... can only filter Category objects because only the Category object has an attribute of products. This predicate says, "Match all Catergory objects in which any related Product object has a nameEn attribute value that contains the search text."
Remember as well that the array you are filtering here:
self.filteredListContent = [[[self fetchedResultsController] fetchedObjects] filteredArrayUsingPredicate:predicate];
...is an array of Category objects and not Product objects.
I think you need to rethink your UI design. Your TableView1 defaults to displaying a list of Category objects but you want your search of that table to display a list of Product objects. That will confuse the user. The user will expect a search on a table of Category objects to return a subset of Category objects.
However, with the existing design, you can produce an array of Product objects with the current code by creating a new array of Product objects by apply the #distinctUnionOfObjects collection operator:
self.filteredListContent = [[[self fetchedResultsController] fetchedObjects] filteredArrayUsingPredicate:predicate];
NSArray *distinctProducts=[self.filteredListContent valueForKey:#"products.#distinctUnionOfObjects.enName"];
... distinctProducts will now be an array of Product objects matching the search criteria. Use that array in configureCell:atIndexPath (you may need to resort it.)
So, I tried these at the configure cell part
NSDictionary *distinctProducts=[self.filteredListContent valueForKey:#"products"];
NSLog(#"what are products:%#",distinctProducts);
NSArray *listofProductsName = [distinctProducts valueForKey:#"nameEN"];
NSLog(#"whatup: %#",listofProductsName);
NSArray *entity = [listofProductsName objectAtIndex:indexPath.row];
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.text = entity;
But then I could convert the name to show...it said _NFSet isEqualToString: ....etc terminated NSException.. though the NSLog of listofProductsName show up the right products name list.