Obj-C, iOS, How do I sort by value and not key, sortedArrayUsingSelector, currently #selector(compare:)] - iphone

I need to sort by value instead of Key, I think....
Heres where I populate my arrarys
const char *sql = "select cid, category from Categories ORDER BY category DESC";
sqlite3_stmt *statementTMP;
int error_code = sqlite3_prepare_v2(database, sql, -1, &statementTMP, NULL);
if(error_code == SQLITE_OK) {
while(sqlite3_step(statementTMP) == SQLITE_ROW)
{
int cid = sqlite3_column_int(statementTMP, 0);
NSString *category = [[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statementTMP, 1)];
NSArray *arr=[[NSArray alloc]initWithObjects:category,nil];
[arrayTmp setObject:arr forKey:[NSString stringWithFormat:#"%i",cid]];
[self.cidList addObject:[NSString stringWithFormat:#"%i",cid]];
[category release];
[arr release];
}
}
sqlite3_finalize(statementTMP);
sqlite3_close(database);
self.allCategories = arrayTmp;
[arrayTmp release];
Heres the method where the arrays are re-sorted.
- (void)resetSearch {
NSMutableDictionary *allCategoriesCopy = [self.allCategories mutableDeepCopy];
self.Categories = allCategoriesCopy;
[allCategoriesCopy release];
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
[keyArray addObject:UITableViewIndexSearch];
[keyArray addObjectsFromArray:[[self.allCategories allKeys]
sortedArrayUsingSelector:#selector(compare:)]];
self.keys = keyArray;
[keyArray release];
}
This is a problem i've had for some time, last time I looked at this I could find an altervative to sortedArrayUsingSelector compare?
EDIT
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [Categories objectForKey:key];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
SectionsTableIdentifier ];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier: SectionsTableIdentifier ] autorelease];
}
cell.textLabel.text = [nameSection objectAtIndex:row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [Categories objectForKey:key];
NSLog(#"the selected cid is = %i",[key intValue]);
selectButton.enabled = YES;
}
Anyone?

Your obviously attempting to construct an array for use in the -[UITableviewDatasource sectionIndexTitlesForTableView:]. As such, you need an array that looks like this (pseudo-code):
[UITableViewIndexSearch, 0_sectionTitle, 1_sectionTitle, 2_sectionTitle, ...]
I think your immediate problem is that you try to add the UITableViewIndexSearch string constant to the array before you sort which makes it impossible for it end up as the first element unless all your other elements sort below U.
The fix is simple, just add the constant after the sort. You can clean the code up while you're at it:
NSMutableArray *secIdx=[NSMutableArray arrayWithCapacity:[[self.allCategories allKeys] count]];
[secIdx addObjectsFromArray:[self.allCategories allKeys]];
[secIdx sortUsingSelector:#selector(compare:)];
[secIdx insertObject:UITableViewIndexSearch atIndex:0];
self.keys=secIdx;
Note that secIdx is autoreleased so you don't have to release it.
Aside from this problem, your code has a lot of unnecessary/dangerous elements that will make your app fragile and hard to maintain.
You are using a lot of init for objects that you could use autoreleased convenience methods for. The 'init`s poise the risk of memory leaks but give you no advantage.
You need to wrap scalar values in objects so they can be easily managed in collections.
You are using an unnecessary array.
You can rewrite the first block like so:
const char *sql = "select cid, category from Categories ORDER BY category DESC";
sqlite3_stmt *statementTMP;
int error_code = sqlite3_prepare_v2(database, sql, -1, &statementTMP, NULL);
if(error_code == SQLITE_OK) {
NSNumber *cidNum; //... move variable declerations outside of loop
NSString *category; //.. so they are not continously recreated
[self.allCategories removeAllObjects]; //... clears the mutable dictionary instead of replacing it
while(sqlite3_step(statementTMP) == SQLITE_ROW){
cidNum=[NSNumber numberWithInt:(sqlite3_column_int(statementTMP, 0))];
category=[NSString stringWithUTF8String:(char *)sqlite3_column_text(statementTMP, 1)];
//... adding the autoreleased category and cidNum to array/dictionary automatically retains them
[self.allCategories addObject:category forKey:cidNum];
[self.cidList addObject:cidNum];
//[category release]; ... no longer needed
//[arr release]; ... no longer needed
}
}
sqlite3_finalize(statementTMP);
sqlite3_close(database);
//self.allCategories = arrayTmp; ... no longer needed
//[arrayTmp release]; ... no longer needed

Use -sortedArrayUsingComparator: (or -sortedArrayUsingFunction:context: if you can't use blocks). Example:
NSDictionary *categories = [self allCategories];
NSArray *keysSortedByValue = [[categories allKeys] sortedArrayUsingComparator:
^(id left, id right) {
id lval = [categories objectForKey:left];
id rval = [categories objectForKey:right];
return [lval compare:rval];
}];

You could make a small model class Category and implement compare inside of it, then sort an array of those objects using that compare:.
Here's some info - How to sort an NSMutableArray with custom objects in it?

Perhaps you're looking for NSSortDescriptor (and the corresponding sort method, -[NSArray sortedArrayUsingDescriptors]) and friends?

If I understood correctly then what you wish to do to get categories from database & display it on a tableView with alphabetical sorting, index on right & search bar on top. Ideally, you would like to display the Contacts application kind of a view. If that's correct, use below code for fetching items from DB & rebuilding (or resetting) it -
const char *sql = "select cid, category from Categories ORDER BY category DESC";
sqlite3_stmt *statementTMP;
NSMutableArray *arrayTmp = [[NSMutableArray alloc] init];
int error_code = sqlite3_prepare_v2(database, sql, -1, &statementTMP, NULL);
if(error_code == SQLITE_OK) {
while(sqlite3_step(statementTMP) == SQLITE_ROW) {
int cid = sqlite3_column_int(statementTMP, 0);
NSString *category = [[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statementTMP, 1)];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:category forKey:#"Category"];
[dict setObject:[NSNumber numberWithInt:cid] forKey:#"CID"];
[arrayTmp addObject:dict];
[dict release];
[category release];
}
}
sqlite3_finalize(statementTMP);
sqlite3_close(database);
self.allCategories = arrayTmp;
[arrayTmp release];
And then rebuild the items using this function -
- (void)rebuildItems {
NSMutableDictionary *map = [NSMutableDictionary dictionary];
for (int i = 0; i < allCategories.count; i++) {
NSString *name = [[allCategories objectAtIndex:i] objectForKey:#"Category"];
NSString *letter = [name substringToIndex:1];
letter = [letter uppercaseString];
if (isdigit([letter characterAtIndex:0]))
letter = #"#";
NSMutableArray *section = [map objectForKey:letter];
if (!section) {
section = [NSMutableArray array];
[map setObject:section forKey:letter];
}
[section addObject:[allCategories objectAtIndex:i]];
}
[_items release];
_items = [[NSMutableArray alloc] init];
[_sections release];
_sections = [[NSMutableArray alloc] init];
NSArray* letters = [map.allKeys sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
for (NSString* letter in letters) {
NSArray* items = [map objectForKey:letter];
[_sections addObject:letter];
[_items addObject:items];
}
}
Now, displaying items in tableView, use below methods -
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView {
if (_sections.count)
return _sections.count;
else
return 1;
}
- (NSInteger)tableView:(UITableView*)tableView sectionForSectionIndexTitle:(NSString *)title
atIndex:(NSInteger)index {
if (tableView.tableHeaderView) {
if (index == 0) {
[tableView scrollRectToVisible:tableView.tableHeaderView.bounds animated:NO];
return -1;
}
}
NSString* letter = [title substringToIndex:1];
NSInteger sectionCount = [tableView numberOfSections];
for (NSInteger i = 0; i < sectionCount; i++) {
NSString* section = [tableView.dataSource tableView:tableView titleForHeaderInSection:i];
if ([section hasPrefix:letter]) {
return i;
}
}
if (index >= sectionCount) {
return sectionCount-1;
} else {
return index;
}
}
- (NSArray*)lettersForSectionsWithSearch:(BOOL)withSearch withCount:(BOOL)withCount {
if (isSearching)
return nil;
if (_sections.count) {
NSMutableArray* titles = [NSMutableArray array];
if (withSearch) {
[titles addObject:UITableViewIndexSearch];
}
for (NSString* label in _sections) {
if (label.length) {
NSString* letter = [label substringToIndex:1];
[titles addObject:letter];
}
}
if (withCount) {
[titles addObject:#"#"];
}
return titles;
} else {
return nil;
}
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [self lettersForSectionsWithSearch:YES withCount:NO];
}
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
if (_sections.count) {
NSArray* items = [_items objectAtIndex:section];
return items.count;
} else {
return _items.count;
}
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (_sections.count)
return [_sections objectAtIndex:section];
return nil;
}
- (id)tableView:(UITableView *)tableView objectForRowAtIndexPath:(NSIndexPath *)indexPath {
if (_sections.count) {
NSArray *section = [_items objectAtIndex:indexPath.section];
return [section objectAtIndex:indexPath.row];
} else {
return [_items objectAtIndex:indexPath.row];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Create your UITableViewCell.
// Configure the cell.
NSDictionary *dict = [self tableView:tableView objectForRowAtIndexPath:indexPath];
cell.textLabel.text = [dict objectForKey:#"Category"];
cell.detailTextLabel.text = [NSString stringWithFormat:%d, [[dict objectForKey:#"CID"] intValue]];
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if (isSearching)
return nil;
NSString *title = #"";
if (_sections.count) {
title = [[_sections objectAtIndex:section] substringToIndex:1];
} else {
return nil;
}
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
view.backgroundColor = [UIColor colorWithRed:(58/255.0) green:(27/255.0) blue:(6/255.0) alpha:1.0];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 1, 50, 18)];
label.textColor = [UIColor whiteColor];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont boldSystemFontOfSize:17.0];
label.text = title;
[view addSubview:label];
[label release];
return [view autorelease];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *dict = [self tableView:tableView objectForRowAtIndexPath:indexPath];
NSLog(#"selected row id:%d, name:%#", [dict objectForKey:#"Category"], [[dict objectForKey:#"CID"] intValue]);
}
The rest part is implementing the UISearchBarDelegate and implementing searching of tableView which can be done using below code:
- (void)searchBar:(UISearchBar *)searchbar textDidChange:(NSString *)searchText {
[_sections removeAllObjects];
[_items removeAllObjects];
if([searchText isEqualToString:#""] || searchText == nil) {
[self rebuildItems];
return;
}
NSInteger counter = 0;
for(NSDictionary *dict in allCategories) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSRange r = [[dict objectForKey:#"Category"] rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(r.location != NSNotFound) {
if(r.location == 0) {
[_items addObject:dict];
}
}
counter++;
[pool release];
}
[contactList reloadData];
}
Hope this is what you're looking for.

On your sorting function u should try this:
NSArray *cntxt; //im not sure this is the correct type that ur using on keyArray
[keyArray addObjectsFromArray:[self.allCategories allKeys]];
[keyArray sortUsingFunction:compareFunction context:cntxt];
And the compare function you modify to your needs
NSInteger compareFunction(id x, id y, void *context) {
//NSArray *ctxt = context;
NSArray *c1 = x;
NSArray *c2 = y;
if ([c1 value] < [c2 value])
return NSOrderedDescending;
else if ([c1 value] > [c2 value])
return NSOrderedAscending;
else
return NSOrderedSame;
}
Edit: After reading your comments and after relooking at your code, it seems like that your keyArray as objects of the type NSString, so you should change:
NSInteger compareFunction(id x, id y, void *context) {
//NSString *ctxt = context;
NSString *c1 = x;
NSString *c2 = y;
NSComparisonResult result;
result = [c1 compare:c2];
if (result<0)
return NSOrderedAscending;
else if (result>0)
return NSOrderedDescending;
else
return NSOrderedSame;
}

Related

How to pass value of db to auto complete text filed?

I created auto complete text box my problem is that how to pass array is stored value which is retrive from db
When use _category detail my app will crash .
if i'm using NSArray with objects there is no problem.
When I debug code i found problem in search method plz help to solve my problem
Thank you so much
My function
- (void)viewDidLoad
{
self.categoryDetail = [CompanyDetailDatabase database].categoryDetail;
NSMutableArray *arrt = [[NSMutableArray alloc]init];
//arrt = [NSMutableArray arrayWithArray:_categoryDetail];
arrt=[NSArray arrayWithArray:_categoryDetail];
self.pastUrls = [[NSMutableArray alloc]initWithArray:arrt];
// self.pastUrls = [[NSMutableArray alloc] initWithObjects:#"Hello1",#"Hello2",#"Hello3", nil];
self.autocompleteUrls = [[NSMutableArray alloc] init];
autocompleteTableView = [[UITableView alloc] initWithFrame:CGRectMake(20, 180, 280, 50) style:UITableViewStylePlain];
autocompleteTableView.delegate = self;
autocompleteTableView.dataSource = self;
autocompleteTableView.scrollEnabled = YES;
autocompleteTableView.hidden = YES;
[self.view addSubview:autocompleteTableView];
[txtProduct setDelegate:self];
}
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring {
// Put anything that starts with this substring into the autocompleteUrls array
// The items in this array is what will show up in the table view
[autocompleteUrls removeAllObjects];
for(NSString *curString in pastUrls)
{
NSRange substringRangeLowerCase = [curString rangeOfString:[substring lowercaseString]];
NSRange substringRangeUpperCase = [curString rangeOfString:[substring uppercaseString]];
if (substringRangeLowerCase.length !=0 || substringRangeUpperCase.length !=0)
{
[autocompleteUrls addObject:curString];
}
}
autocompleteTableView.hidden =NO;
[autocompleteTableView reloadData];
}
#pragma mark UITextFieldDelegate methods
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
autocompleteTableView.hidden = NO;
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}
#pragma mark UITableViewDataSource methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return autocompleteUrls.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = #"AutoCompleteRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier] autorelease];
}
cell.textLabel.text = [autocompleteUrls objectAtIndex:indexPath.row];
return cell;
}
#pragma mark UITableViewDelegate methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
txtProduct.text = selectedCell.textLabel.text;
}
Now view of scene image
I'm not sure about your methods. But, it is very simple to achieve. First you've to insert some records in your database table. And, while editing on your UITextField you have to pass the text to your database table as sqlite query with your conditions and returns as NSArray or NSMutableArray Some code snippets -
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == listTableView)
{
recordsArray = [self getRecords:string];
if ([recordsArray count] == 0 || recordsArray == NULL)
{
[[[UIAlertView alloc] initWithTitle:nil message:#"No Records Were found" delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil, nil] show];
}
else
{
tableV.hidden = NO;
[tableV reloadData];
}
}
return YES;
}
Above will get your typed string and pass to database method named as getRecords with typed string.
-(NSMutableArray*)getRecords:(NSString *)srchString
{
NSMutableArray *mutArray = [[NSMutableArray alloc]init];
sqlite3 *servicesDB;
NSString *filePath=[AppDelegate dbPath];
if(sqlite3_open([filePath UTF8String], &servicesDB) == SQLITE_OK)
{
NSString *sqlStatement;
sqlStatement = [NSString stringWithFormat:#"SELECT * FROM Records WHERE record = '%%%#%%'", srchString];
const char *sql = [sqlStatement UTF8String];
sqlite3_stmt *select_statement;
if (sqlite3_prepare_v2(servicesDB, sql, -1, &select_statement, nil) == SQLITE_OK)
{
while (sqlite3_step(select_statement) == SQLITE_ROW)
{
char *record = (char *)sqlite3_column_text(select_statement, 0);
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:[NSString stringWithUTF8String:record] forKey:#"record"];
[mutArray addObject:[dict copy]];
}
}
else
{
NSLog(#"Error while fetching data. '%s'", sqlite3_errmsg(servicesDB));
}
sqlite3_finalize(select_statement);
}
sqlite3_close(servicesDB);
return mutArray;
}
Above database method will execute and fetch the data which are all having word whatever you're typed. You can find the details about LIKE clause here
You'll get your final result once the executions are completed. Simply find a sample project here

Remove all items from indexPathsForSelectedItems, UICollectionView

How to remove all the items from indexPathSelectdItems. Below is my code I am using to save values to array from indexPathSelectedITems, but need to clear the array when section changes and array should save value as a fresh. But indexPathForSelectedItems add previousSelectedValues also.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSString *seatV;
int cs;
NSString *secVal = [arrSeatSel objectAtIndex:indexPath.section];
NSArray *arrSplit = [secVal componentsSeparatedByString:#":"];
seatV = [arrSplit objectAtIndex:1];
cs = [seatV integerValue];
int v;
NSString *cnt = [NSString stringWithFormat:#"%#",[arrTot objectAtIndex:indexPath.section]];
v = [cnt intValue];
NSString *sect = [NSString stringWithFormat:#"%d", indexPath.section];
if(indexPath.item < v)
{
if([sectionInfo count] < cs)
{
itemPaths = [self.collectionView indexPathsForSelectedItems];
//NSMutableArray *array = [NSMutableArray array];
//array = [self.collectionView indexPathsForSelectedItems];
//sectionInfo = [self.collectionView indexPathsForSelectedItems];
sectionInfo = [NSMutableArray arrayWithArray: [self.collectionView indexPathsForSelectedItems]];
//[sectionInfo addObject:[[self.collectionView indexPathsForSelectedItems] lastObject]];
[selectedItemsInfo setObject:sectionInfo forKey:sect];
cell=[self.collectionView cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"yellow_seat.png"]];
//sectionInfo1 = sectionInfo;
}
else
{
[self.collectionView deselectItemAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row inSection:indexPath.section] animated:YES];
[sectionInfo1 addObject:[selectedItemsInfo objectForKey:sect]];
[selectedItemsInfo setObject:sectionInfo1 forKey:sect];
[sectionInfo removeAllObjects];
}
}
else
{
[self.collectionView deselectItemAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row inSection:indexPath.section] animated:YES];
}
NSLog(#"section array:%#", sectionInfo);
NSLog(#"section array1:%#", sectionInfo1);
NSLog(#"selected seats dict:%#", selectedItemsInfo);
}
So, how to clear previous values indexPathSelectedItems so that it can hold new selected values only?
Try using this code as per your requirement.
[self deleteItemsFromDataSourceAtIndexPaths:selectedItemsIndexPaths];
OR
[self.collectionView deleteItemsAtIndexPaths:selectedItemsIndexPaths];

how to assign a static row at the first and last row of dynamically allocated data in table view

i m parsing a json file and populating it in my table view what i want to assign is a static row.at the first and last row of my tableview named as Var tycker du. but doing so.it overlaps the dynamically allocated data from json file..could you guys help me out below is the code.
static NSString * const kCellTextKey = #"CellTextKey";
static NSString * const kCellStateKey = #"CellStateKey";
static NSString* kAppId = #"126013844184727";
#define KFBAccessToken #"126013844184727"
#define KFBExpirationDate #"KFBExpirationDate"
#implementation Tab5
#synthesize tableview1,jsonData,jsonArray,story,media1,url,descriptiondesc,media2;
#synthesize arForIPs = _arForIPs;
- (void)viewDidLoad {
[super viewDidLoad];
objMan = [[HJObjManager alloc] initWithLoadingBufferSize:6 memCacheSize:20];
self.arForIPs=[NSMutableArray array];
self.tableview1.backgroundColor=[UIColor clearColor];
[self.tableview1 setAllowsSelectionDuringEditing:TRUE];
jsonurl=[NSURL URLWithString:#"http://dev-parkguiden.knutpunkten.se/Api/GetPark? parkid=3"];
NSURLRequest *request = [NSURLRequest requestWithURL:jsonurl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
connection1=[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
self.jsonData=[NSData dataWithContentsOfURL:jsonurl];
NSDictionary *items=[NSJSONSerialization JSONObjectWithData:self.jsonData options:NSJSONReadingMutableLeaves error:nil];
items1 = [items objectForKey:#"ThingsTodo"];
story = [[NSMutableArray array]retain];
media1 = [[NSMutableArray array]retain];
url=[[NSMutableArray array]retain];
media2=[[NSMutableArray array]retain];
descriptiondesc=[[NSMutableArray array]retain];
dog=[[NSMutableArray array]retain];
arr=[[NSMutableArray array]retain];
bose=[[NSMutableArray array]retain];
for (NSDictionary *item in items1)
{
[self.story addObject:[item objectForKey:#"Name"]];
[self.media1 addObject:[item objectForKey:#"Status"]];
//[self.media2 addObject:[item objectForKey:#"Image"]];
}
//NSLog(#"room:%#",items1);
[self makeNewArray];
}
-(void)makeNewArray
{
for ( int i=0; i<[self.media1 count]; i++)
{
NSDictionary *boy=[self.media1 objectAtIndex:i];
NSString *str=[[NSString alloc]initWithFormat:#"%#",boy];
//NSLog(#"the value:%#",str);
if([str isEqualToString:#"1"])
{
text = [self.story objectAtIndex:i];
NSString *text1 = [NSString stringWithFormat:#"%#",text];
NSNumber *state = [NSNumber numberWithBool:NO];
dict=[NSDictionary dictionaryWithObjectsAndKeys:text1,kCellTextKey,state,kCellStateKey,nil];
[arr addObject:dict];
// [dog addObject:[self.story objectAtIndex:i]];
}
dog=[arr mutableCopy];
NSLog(#"wat hav i got:%#",arr);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [dog count];
}
- (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]; }
// cell.textLabel.text=[dog objectAtIndex:indexPath.row];
NSDictionary *rowData = [dog objectAtIndex:indexPath.row];
cell.textLabel.text = [rowData objectForKey:kCellTextKey];
if ([[rowData objectForKey:kCellStateKey] boolValue]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
[bose removeObject:[newDict valueForKey:#"CellTextKey"]];
// NSLog(#"object going to get removed:%#",bose);
}
sectionRows = [tableview1 numberOfRowsInSection:[indexPath section]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *dict = [dog objectAtIndex:indexPath.row];
BOOL newState = ![[dict objectForKey:kCellStateKey] boolValue];
newDict = [NSDictionary dictionaryWithObjectsAndKeys:[dict objectForKey:kCellTextKey], kCellTextKey, [NSNumber numberWithBool:newState], kCellStateKey, nil];
[dog replaceObjectAtIndex:indexPath.row withObject:newDict];
[bose addObject:[newDict valueForKey:#"CellTextKey"]];
NSLog(#"the current added data:%#",bose);
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
}
hey try out with this solution
-(void)makeNewArray
{
for ( int i=0; i<[self.media1 count]; i++)
{
NSDictionary *boy=[self.media1 objectAtIndex:i];
NSString *str=[[NSString alloc]initWithFormat:#"%#",boy];
//NSLog(#"the value:%#",str);
if([str isEqualToString:#"1"])
{
text = [self.story objectAtIndex:i];
NSString *text1 = [NSString stringWithFormat:#"%#",text];
NSNumber *state = [NSNumber numberWithBool:NO];
dict=[NSDictionary dictionaryWithObjectsAndKeys:text1,kCellTextKey,state,kCellStateKey,nil];
[arr addObject:dict];
// [dog addObject:[self.story objectAtIndex:i]];
}
}
NSDictionary *dict;
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Var tycker du", #"CellTextKey",
#"0", #"CellStateKey", nil];
[dog addObject:dict];
for(int i=0; i<arr.count; i++){
[dog addObject:[arr objectAtIndex:i]];
}
[dog addObject:dict];
// dog=[arr mutableCopy];
NSLog(#"wat hav i got:%#",dog);
}

search bar not working?

i have a SQL file where 5 different type of data is stored. I am adding this data in a dictionary specified with keys. and then i am adding this dictionary to tableData array as a dataSource for table and searchBar. But it is not searching anything.
adding code below
- (void)viewDidLoad {
[super viewDidLoad];
dataSource =[[NSMutableArray alloc] init];
tableData = [[NSMutableArray alloc]init];
searchedData = [[NSMutableArray alloc]init];
NSString *query = [NSString stringWithFormat:#"SELECT * FROM Vegetables"];
SQLite *sqlObj1 = [[SQLite alloc] initWithSQLFile:#"ShoppersWorld.sqlite"];
[sqlObj1 openDb];
[sqlObj1 readDb:query];
// [query release];
for (int i=0; i<[dataSource count]; i++) {
NSLog(#"data:%#",[dataSource objectAtIndex:i]);
}
while ([sqlObj1 hasNextRow])
{
NSString *name=[sqlObj1 getColumn:1 type:#"text"];
NSString *price=[sqlObj1 getColumn:2 type:#"text"];
NSString *quantity=[sqlObj1 getColumn:3 type:#"text"];
NSString *unit=[sqlObj1 getColumn:4 type:#"text"];
NSString *total=[sqlObj1 getColumn:5 type:#"text"];
dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys: name,#"nameOfVegetables",
price,#"priceOfVegetables",
quantity,#"quantityOfVegetables",
unit,#"unitOfVegetables",
total,#"totalPriceOfVegetables",nil];
//NSLog(#"results:%# %#",dict);
[dataSource addObject:dict];
}
[tableData addObjectsFromArray:dataSource];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
// Configure the cell.
else {
cell.productLbl.text= [NSString stringWithFormat:#"%#",[[tableData objectAtIndex:indexPath.row]objectForKey:#"nameOfVegetables"] ];
cell.bPriceLbl.text = [NSString stringWithFormat:#"Rs %d/Kg",
[[[tableData objectAtIndex:indexPath.row] objectForKey:#"priceOfVegetables"] intValue]];
cell.qtyLbl.text = [NSString stringWithFormat:#"QTY: %# %#",[[tableData objectAtIndex:indexPath.row]
objectForKey:#"quantityOfVegetables"],[[tableData objectAtIndex:indexPath.row] objectForKey:#"unitOfVegetables"]] ;
cell.tPriceLbl.text = [NSString stringWithFormat:#"TOTAL: %#",[[tableData objectAtIndex:indexPath.row]
objectForKey:#"totalPriceOfVegetables"]];
}
return cell;
}
#pragma search operations
- (IBAction)search:(id)sender{
sBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0,40,320,30)];
sBar.delegate = self;
[self.view addSubview:sBar];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
// only show the status bar’s cancel button while in edit mode
[sBar setShowsCancelButton:YES animated:YES];
sBar.autocorrectionType = UITextAutocorrectionTypeNo;
// flush the previous search content
[tableData removeAllObjects];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{
[sBar setShowsCancelButton:NO animated:YES];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
[tableData removeAllObjects];// remove all data that belongs to previous search
if([searchText isEqualToString:#""] || searchText==nil){
[tableview reloadData];
return;
}
NSInteger counter = 0;
for(NSString *name in dataSource)
for (int i = 0; i < [dataSource count]; i++)
{
NSMutableDictionary *temp = (NSMutableDictionary*) [dataSource objectAtIndex:i];
NSString *name = [NSString stringWithFormat:#"%#", [temp valueForKey:#"nameOfVegetables"]];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSRange r = [name rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(r.location != NSNotFound)
{
if(r.location== 0)//that is we are checking only the start of the names.
{
[tableData addObject:name];
}
}
counter++;
[pool release];
}
[tableview reloadData];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
sBar.hidden= YES;
// if a valid search was entered but the user wanted to cancel, bring back the main list content
[tableData removeAllObjects];
[tableData addObjectsFromArray:dataSource];
#try{
[tableview reloadData];
}
#catch(NSException *e){
}
[sBar resignFirstResponder];
sBar.text = #"";
}
In search delegate methods you manipulate not with searchedData but tableData array. As these name suggest, array searchedData is supposed to store filtered data.
By the way, your approach to use sqlite for data source and absorbing all database into array is wrong. In cellForRowAtIndexPath read from sqlite database only data you need at the moment.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// load from sqlite only data for this cell.
// Use searchBar.text with sqlite's LIKE to filter data from database
NSUInteger row = [indexPath row];
static NSString *CellIdentifier = #"SignsCellIdentifier";
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
NSString *sql = [NSString stringWithFormat:#"SELECT fieldNameFromTable FROM TableName WHERE FieldToLookForIn LIKE \"%%%#%%\" LIMIT 1 OFFSET %u", searchBar.text ? searchBar.text : #"", row];
sqlite3_stmt *stmt;
int res = sqlite3_prepare_v2(database, [sql UTF8String], -1, &stmt, NULL);
if (res != SQLITE_OK) {
NSLog(#"sqlite3_prepare_v2() failed"];
return nil;
}
if (sqlite3_step(stmt) == SQLITE_ROW) {
const unsigned char *name = sqlite3_column_text(stmt, 0);
cell.text = [NSString stringWithUTF8String:(const char*)name];
}
sqlite3_finalize(stmt);
return cell;
}
How to apply search in this approach? In textDidChange do nothing but call [tableView reloadData]. And in cellForRowAtIndexPath load data with sqlite LIKE using searchBar.text as search term. So reloadData will load only filtered records. searchBarSearchButtonClicked will call only resignFirstResponder of it's caller, removing keyboard off screen. It doesn't need to do anything more because search is already done. searchBarCancelButtonClicked will set text property of it's caller to nil, call reload data and again call resignFirstResponder.
- (void)searchBarCancelButtonClicked:(UISearchBar *)s {
s.text = nil;
[tableView reloadData];
[s resignFirstResponder];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)s {
// search is already done
[s resignFirstResponder];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[tableView reloadData];
}
numberOfRowsInSection should also request db with the same SELECT as in cellForRowAtIndexPath, but with SELECT COUNT. Writing this method will be your homework)

UISearchBar in iPhone/iPad application

I have data like this...(All the data comes from .plist file...)
Searching Array - (
{
FirstName = "Ramesh";
LastName = "Bean";
EmpCode = 1001;
},
{
FirstName = "Rohan";
LastName = "Rathor";
EmpCode = 102;
},
{
FirstName = "Priya";
LastName = "Malhotra";
EmpCode = 103;
},
{
FirstName = "Mukesh";
LastName = "Sen";
EmpCode = 104;
},
{
FirstName = "Priya";
LastName = "Datta";
EmpCode = 105;
}
)
I want implement search data from this array on the basis of FirstName (key).
I am able to search data with the "FirstName(Key)"
but after filtering data suppose i clicked Row( in the data) which is displayed in the TableView. It Navigate me to New-Controller with all the information of that particular employee (like: FirstName,LastName,EmpCode).
How can i get information?
As i gone through the search sample codes.
Here is my search code...
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
NSInteger TotalNoOfRecords=[self.SearchtableDataSource count];
for (int i=0;i<TotalNoOfRecords;i++)
{ NSDictionary *dictionary = [self.SearchtableDataSource objectAtIndex:i];
NSArray *array = [dictionary objectForKey:#"FirstName"];
[searchArray addObject:array];
}
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
{
[copyListOfItems addObject:sTemp];
}
}
How can i improve this code?....Please guide me... [searchArray release]; searchArray = nil;
How we maintain all the "Keys(FirstName,LastName,EmpCode)" in the searchArray please help me out? Thanks...
I think the best approach would be to make an array of NSDictionary which has value for three keys namely "FirstName", "LastName", "EmpCode"
now to filter the data according to "FirstName" use NSPredicate instead of for loop,
NSString *searchText = searchBar.text;
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"FirstName like[cd] %#",searchText];
NSArray* filteredArray = [self.SearchtableDataSource filteredArrayUsingPredicate:predicate];
In method cellForRowAtIndexPath
NSDictionary* currentEmp = [filteredArray objectAtIndex:inddexPath.row];
display the information in this currentEmp.
Similarly in didSelectRowAtIndexPath
NSDictionary* currentEmp = [filteredArray objectAtIndex:inddexPath.row];
and pass this dictionary in the next ViewController in which u want to dispaly the detail of the current employ.
if u have two table views one that of searchDisplayController (showing the filtered result)
and one which is showing the whole result, then u can track this by having a BOOL variable tacking that is if filtering is active or not.
Here is what i have done and its working fine with me(tested it). I have taken one IBOutlet of UISearchBar so here is the code for ur .h file
#interface SearchForEmp : UIViewController<'UISearchDisplayDelegate,UISearchBarDelegate,UITableViewDelegate,UITableViewDataSource> {
IBOutlet UISearchBar* mySearchBar;
UISearchDisplayController* mySearchDisplayController;
NSMutableArray* allEmp;
NSMutableArray* filteredEmp;
BOOL isFilatering;
}
#end
Now in .m file
-(void)viewDidLoad
{
[super viewDidLoad];
mySearchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:mySearchBar contentsController:self];
mySearchDisplayController.searchResultsDelegate = self;
mySearchDisplayController.searchResultsDataSource = self;
mySearchDisplayController.delegate = self;
isFilatering = NO;
filteredEmp = [[NSMutableArray alloc] init];
allEmp = [[NSMutableArray alloc] init];
NSDictionary *temp;
for (int i = 0; i < 30; i++) {
temp = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:#"FirstName_%d",i],#"FirstName",[NSString stringWithFormat:#"LastName_%d",i],#"LastName",[NSNumber numberWithInt:1000+i],#"EmpCode",nil];
[allEmp addObject:temp];
}
}
for e.g purpose i have thake an array of 30 Dictionaries, each with a unique name.For table view data source and delegate .....
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isFilatering) {
return [filteredEmp count];
}
else {
return [allEmp count];
}
return [allEmp count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] init] autorelease];
}
NSDictionary* temp;
if (isFilatering) {
temp = [filteredEmp objectAtIndex:indexPath.row];
}
else {
temp = [allEmp objectAtIndex:indexPath.row];
}
cell.textLabel.text = [NSString stringWithFormat:#"%# %#",[temp objectForKey:#"FirstName"],[temp objectForKey:#"LastName"]];
return cell;
}
Now as far as searching is concerned here is what u need to do .......
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
NSPredicate* predicate = [[NSPredicate predicateWithFormat:#"self.FirstName contains %#",mySearchBar.text] retain];
filteredEmp = [[allEmp filteredArrayUsingPredicate:predicate] retain];
}
-(void) searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
isFilatering = YES;
}
-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
isFilatering = NO;
}
I hope that helps you understanding the things, dont forget to add retain in line
filteredEmp = [[allEmp filteredArrayUsingPredicate:predicate] retain];
because method filteredArrayUsingPredicate: is an accessor method and its retain count is handled by the NSArray so have access to the filtered array u need to pass a retain msg to it.