how to implement Search feature in ios 7? - ios7

I am working on ios 7 app, I am developing animals details app. I have created first table view for animals category list, second tableview for list of animals in a particular category and third web view for animals detailed web view. I need to implement search feature in first screen that should display search items depends on user queries. How to implement this feature.

Implement search on an array through which you create your first tableview.
Take a tempArray for holding the sorted data from the initial tableView.
tempArray = [NSmutableArray alloc]init];
2.For ex lets say user enter a search string "S".
3.Loop through your array from which you created your first tableView.
for(int i = 0, i< [yourArray count], i++)
{
NSString *str = [yourArray objectAtIndex:i];
if ([str rangeOfString:#"S"].location == NSNotFound) {
NSLog(#"str does not contain your searched string");
} else {
[tempArray addObject:str];
}
}
Now Reload your tableview using your tempArray.
Just for showing the core functionality i have used a static string entered by user, you can create it dynamic using property and assigned it a string entered by user then implement the search.

Related

How can I get number of returned results from NSArray Controller in cocoa app?

I have an NSArrayController named productsArrayController which is binded with an NSTableViev and returns records from core data. I want now programmatically to get the number of the records that are displayed in the NSTableView.
I know that I should do that from the data source (productsArrayController in my case) not from the NSTableView, so I make an outlet from my NSArrayController. Here is what I am trying to do:
- (void)viewDidLoad {
NSArray *myArr = [_productsArrayController selectedObjects];
NSUInteger total = [myArr count];
NSLog(#"Total is: %ld",total);
}
Sure enough since I have no selected objects at this time, the above code returns 0, even that I have 9 records displayed in my NSTableView. Question is what should I use instead of selectedObjects to get the number of the records (9 in my case) here?
You can do one thing in applicationDidFinishLaunching: add
NSError *error;
BOOL ok = [productsArrayController fetchWithRequest:nil merge:NO error:&error];
int count = [[productsArrayController arrangedObjects] count];
Answer taken from the following thread URL

How to add imagepath inside array one by one in iphone

I am new to iPhone programming. How do I add an NSString to an NSArray. I have thumbnail images. If I click on any one of the images I want to store imagepath in the NSArray. Same if I click on the same image I want to remove the imagepath from NSArray. (like select and deselect) Can anybody tell me how I can do this, what is the logic for that? Till now I have been doing
- (void)click
{
NSLog(#"%#",_fullsizeUrl);
array =[[NSMutableArray alloc]init];
[array addObject:_fullsizeUrl];
NSLog(#"%#",array);
}
In above code _fullsizeUrl is imagepath I am storing this in an NSMutableArray. The problem is if select any one image means Ii getting image path that is storing in NSArray. But if I select any other images it's storing the latest one previous one is removing. Can any body tell me how to do this
Thanks
Your "previous one is removing" because you are reallocating your NSMutableArray everytime you tap the thumbnail. Allocate the array outside the click method.
-(void)click
{
if ([yourAry containsObject:yourObject])
{
[yourAry removeObject:yourObject];
}
else{
[yourAry addObject:yourObject];
}
}
array =[[NSMutableArray alloc]init];
[array addObject:_fullsizeUrl];
You are creating a new array every time click is called. At the end of the method, the array has no strong references (assuming ARC, otherwise you are leaking memory) and gets deallocated.
Make your NSMutableArray a property on your class and then click should look like this:
- (void)click
{
if ([self.myArray containsObject:self.fullSizeUrl]) {
[self.myArray removeObject:self.fullSizeUrl];
} else {
[self.myArray addObject:self.fullSizeUrl];
}
}
If you are only storing unique strings in your array you could consider using NSMutableSet instead.
You can use this method and use one int variable i and increase ever time +1.
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;

How can I populate a sparse UITableView from a fetched results object?

In my sweet app you can use two kinds of items from a list of items. There are equipable items, and bag items. When you navigate to the inventory screen, there are two sections of a table view, each with 4 cells. Four cells for equipped items, and four cells for items in your "bag". If you don't have anything equipped, the cells just say "empty".
How can I populate table cells conditionally based on the shape of my results object?
Here is the code I wish I had:
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// this returns 'nil' if the index path was out of bounds
NSManagedObject * item = [self.fetchedResultsController carefullyGetObjectAtIndexPath:indexPath];
if (nil == item) {
cell.textLabel.text = #"empty";
} else {
cell.textLabel.text = [item valueForKey:#"name"];
}
}
Some problems I've encountered trying to implement this 'careful' objectAtIndexPath:
I tried bounds checking, but I'm having trouble because the fetchedArray is flat, while the conceptual model I am trying to navigate is not flat: rows are 'in' sections.
I tried using a try/catch, but then I remembered that the out-of-bounds elements are undefined, not nil... so sometimes I get an error that I can catch and react to, and sometimes I just get random interesting stuff. The setup I have now:
#try {
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
return managedObject;
}
#catch (NSException * e) {
return nil;
}
consistently gives me 5 entries, 4 in the right places and 1 odd-ball which is a repeat from the other section.
Not sure how to navigate the fetched results manually. I'm playing with four items, 2 of each kind. I had hoped it would be as easy as a doubly nested array, with sections on the outside and rows on the in. It seems that things are trickier than this. When I inspect the fetchedResults NSArray, I see that it is flat. All the "bag" items are first, and the "equipable" come next. I don't imagine I can depend on this ordering, though, so I don't feel safe making a mapping function to go from indexPath section to array index. (I could be convinced to feel safe about this).
An alternative I thought of involves populating my inventory with 8 'empty' items that would be returned as place holder results when the sections don't get completely filled. This doesn't sit well with me though.
I realize why this isn't working: tables aren't supposed to have 'empty' rows. But I want my table to have empty rows!
UPDATE
Here's the method I'm using for now...
- (NSManagedObject*) carefullyGetObjectAtIndexPath:(NSIndexPath*)indexPath
{
NSLog(#"in %# %s", [self class], _cmd);
NSString * desiredType = (indexPath.section == BAG_SECTION)? #"bag" : #"equipable";
NSArray * fetchedObjects = [self.fetchedResultsController fetchedObjects];
NSInteger sectionStartIndex = -1;
// iterate until you hit a type you like
NSUInteger i, count = [fetchedObjects count];
for (i = 0; i < count; i++) {
NSObject * obj = [fetchedObjects objectAtIndex:i];
NSString * fetchedType = (NSString*)[obj valueForKey:#"type"];
if ([desiredType isEqualToString:fetchedType]) {
sectionStartIndex = i;
break;
}
}
if (-1 == sectionStartIndex) {
// maybe there aren't any of that type of item
} else {
NSInteger calculatedEntityIndex = sectionStartIndex + indexPath.row;
NSLog(#"calculated index %d", calculatedEntityIndex);
// if we are still in the array
if (calculatedEntityIndex < [fetchedObjects count]) {
// then we can get the object
NSManagedObject * entity = [fetchedObjects objectAtIndex:calculatedEntityIndex];
// and if we are still in the right section
NSString * typeForEntityAtIndex = [entity valueForKey:#"type"];
if ([desiredType isEqualToString:typeForEntityAtIndex]) {
// then this is what we wanted
return entity;
}
}
}
return nil;
}
I just really don't feel I should have to iterate over something like this...
z.
Full disclosure: this is a term project, but the project is to make the app by any means necessary. This includes third party libraries, asking questions on stackoverflow, &c... The goal of this term project is to experience working on something bigger, like a sweet app, not to learn objective-c.
Ziggy,
The NSFetchedResultsController has many limitations. If you cannot make your schema meet its exacting requirements and it appears you probably haven't, then you should construct your tableView out of multiple NSFetchRequests. It is straightforward. Most of the interesting tableViews do just this. Core Data really works best when you perform larger fetches and then refine the search using the set and filter operations on the collection classes.
tableViews can have empty rows. You just have to coordinate this with custom code in your various delegate and cell configuration code.
You have a lot of options to solve your problem. It appears you are unhappy with a quite limited framework API. You're a budding programmer. Roll your own.
Andrew
P.S. You have a curious goal to write a Mac OS X/iOS app without needing to learn Objective-C. You actually have chosen the one technology in the framework, Core Data, that exercises Objective-C to its maximum capability. (In my opinion, as an educator of iOS programmers, your education would probably be better served learning the intricacies of a very different persistence model, Core Data's model, than retreating to mundane, mainstream SQL solution.) If you would prefer to use a different language, MacRuby/RubyMotion is quite effective.

NSMutableArray of nsstrings (in one of the UISearchBar delegates) possible with persistent storage?

I would like to make a history list in my app. I have surfed and looked at many questions here, but so far I havenĀ“t found the answer to my question.
My codes:
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
NSLog (#"search bar text did end editing!");
NSString *bookmarked = mySearchBar.text;
NSMutableArray *bookmarkl = [[NSMutableArray alloc] init];
int i;
for (i = 0; i < [bookmarkl count]; i ++)
{
[bookmarkl addObject:bookmarked];
}
for (NSString *sa in bookmarkl);
NSLog (#"whole array: %#", bookmarkl);
}
But all I get is one string at a time. What is wrong?
I want to add a new string to the mutable array, how should I do this?
You are creating a new list every time the function is called. You should add bookmarkl to your class as a property and only create it once during initialization. If you want the history to persist when your app is closed you will also want to write the data to a file. You can use [NSMutableArray arrayWithContentsOfFile] to load the history and writeToFile to save it.

Using Array Controllers to restrict the view in one popup depending on the selection in another. Not core data based

I am working on an app that is not core data based - the data feed is a series of web services.
Two arrays are created from the data feed. The first holds season data, each array object being an NSDictionary. Two of the NSDictionary entries hold the data to be displayed in the popup ('seasonName') and an id ('seasonID') that acts as a pointer (in an external table) by matches defined for that season.
The second array is also a collection of NSDictionaries. Two of the entries hold the data to be displayed in the popup ('matchDescription') and the id ('matchSeasonId') that points to the seasonId defined in the NSDictionaries in first array.
I have two NSPopUps. I want the first to display the season names and the second to display the matches defined for that season, depending on the selection in the first.
I'm new at bindings, so excuse me if I've missed something obvious.
I've tried using ArrayControllers as follows:
SeasonsArrayController:
content bound to appDelegate seasonsPopUpArrayData.
seasonsPopup:
content bound to SeasonsArrayController.arrangedObjects; content value bound to SeasonsArrayController.arrangedObjects.seasonName
I see the season names fine.
I can obviously follow a similar route to see the matches, but I then see them all, instead of restricting the list to the matches for the season highlighted.
All the tutorials I can find seem to revolve around core data and utilise the relationships defined therein. I don't have that luxury here.
Any help very gratefully received.
This is not an answer - more an extension of the previous problem.
I created MatchesArrayController and subclassed it from NSArrayController to allow some customisation.
Following the example in 'Filtering Using a Custom Array Controller' from 'Cocoa Bindings Topics', I followed the same idea as above:
MatchessArrayController: content bound to appDelegate matchesPopUpArrayData.
matchesPopup: content bound to MatchesArrayController.arrangedObjects; content value bound to MatchesArrayController.arrangedObjects.matchDescription.
I've derived the selected item from seasonPopUp:sender and used this to identify the seasonId.
The idea is to change the arrangedObjects in MatchesArrayController by defining the following in;
- (NSArray *)arrangeObjects:(NSArray *)objects
{
if (searchString == nil) {
return [super arrangeObjects:objects];
}
NSMutableArray *filteredObjects = [NSMutableArray arrayWithCapacity:[objects count]];
NSEnumerator *objectsEnumerator = [objects objectEnumerator];
id item;
while (item = [objectsEnumerator nextObject]) {
if ([[[item valueForKeyPath:#"matchSeasonId"] stringValue] rangeOfString:searchString options:NSAnchoredSearch].location != NSNotFound) {
[filteredObjects addObject:item];
}
}
return [super arrangeObjects:filteredObjects];
}
- (void)searchWithString:(NSString *)theSearchString {
[self setSearchString:theSearchString];
[self rearrangeObjects];
}
- (void)setSearchString:(NSString *)aString
{
[aString retain];
[searchString release];
searchString=aString;
}
I've used NSLog to check that things are happening the way they are supposed to and all seems ok.
However, it still doesn't do what I want.
[self rearrangeObjects]; is supposed to invoke the arrangeObjects method but doesn't. I have to call it explicity
(i.e.[matchesArrayController arrangeObjects:matchesPopUpArrayData]; )
Even then, although filteredObjects gets changed the way it is supposed to, the drop down list does not get updated the way I want it to.