UISearchBar - search a NSDictionary of Arrays of Objects - iphone

I'm trying to insert a search bar in a tableview, that is loaded with information from a NSDictionary of Arrays. Each Array holds and object. Each object has several properties, such as Name or Address.
I've implemented the methods of NSSearchBar, but the code corresponding to the search it self, that i have working on another project where the Arrays have strings only, is not working, and I can't get to thr problem.
Here's the code:
'indiceLateral' is a Array with the alphabet;
'partners' is a NSDictionary;
'RLPartnersClass' is my class of Partners, each one with the properties (name, address, ...).
-(void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.indiceLateral) {
NSMutableArray *array = [partners valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array) {
if ([name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.indiceLateral removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[theTable reloadData];
}
Can anyone help me please?
Thanks,
Rui Lopes

I've done it.
Example:
-(void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableDictionary *finalDict = [NSMutableDictionary new];
NSString *currentLetter = [[NSString alloc] init];
for (int i=0; i<[indiceLateral count]; i++) {
NSMutableArray *elementsToDict = [[[NSMutableArray alloc] init] autorelease];
currentLetter = [indiceLateral objectAtIndex:i];
NSArray *partnersForKey = [[NSArray alloc] initWithArray:[partnersCopy objectForKey:[indiceLateral objectAtIndex:i]]];
for (int j=0; j<[partnersForKey count]; j++) {
RLNames *partnerInKey = [partnersForKey objectAtIndex:j];
NSRange titleResultsRange = [partnerInKey.clientName rangeOfString:searchTerm options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0){
NSLog(#"found: %#", partnerInKey.clienteCity
[elementsToDict addObject:partnerInKey];
}
}
[finalDict setValue:elementsToDict forKey:currentLetter];
}
NSMutableDictionary *finalResultDict = [finalDict mutableDeepCopy];
self.partners = finalResultDict;
[finalResultDict release];
[theTable reloadData];
}

Related

how can print array json values into uitableview in iphone

JSON format code looks like this:
{
"rates": {
"amc": "201",
"hyd": "500.50",
"guj": "200.10",
"afgd": "400"
}
}
After parsing JSON values the above code array returns:
array = [values valueForKey:#"rates"];
which array return
{
amc = "201";
hyd = "500.50";
guj = "200.10";
afgd = "400";
...........etc
}
But i want to print in UITableView look amc:201
How can i do this?
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
self.responseData = nil;
values = [responseString JSONValue];
array = [[NSMutableArray alloc] init];
NSMutableArray *arrTitle = [[NSMutableArray alloc] init];
NSMutableArray *arrValues = [[NSMutableArray alloc] init];
array =[values valueForKey:#"rates"];
NSLog(#"array values:--> %#",array);
// NSLog(#"values:--> %#",values);
// NSLog(#"Particular values:--> %#",[[values valueForKey:#"rates"] valueForKey:#"AED"]);
tempDict1 = (NSMutableDictionary *)array;
NSArray *arr;// =[[NSArray alloc]init];
arr = [[tempDict1 valueForKey:#"rates"] componentsSeparatedByString:#";"];
NSLog(#"arr-->%#",arr);
NSString *subStar = #"=";
[arrTitle removeAllObjects];
[arrValues removeAllObjects];
for (int i=0; i<[arr count]-1; i++)
{
[arrTitle addObject:[[arr objectAtIndex:i] substringToIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:subStar])-1]];
[arrValues addObject:[[arr objectAtIndex:i] substringFromIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:subStar])]];
NSLog(#"arrTitle is:--> %#",arrTitle);
}
tempDict1 = (NSMutableDictionary*)[array objectAtIndex:0];
array = [values valueForKey:#"rates"];
NSLog(#"tempDict--%#",[tempDict1 objectForKey:#"AED"]);
[array retain];
[tbl_withData reloadData];
}
try:
NSMutableArray * array2=[[NSMutableArray alloc]init];
[array addObject: [[array objectAtIndex:0] objectForKey:#"amc"]];
[array addObject: [[array objectAtIndex:0] objectForKey:#"hyd"]];
[array addObject: [[array objectAtIndex:0] objectForKey:#"guj"]];
[array addObject: [[array objectAtIndex:0] objectForKey:#"afgd"]];
now put array2 values in your table cell.
like:
cell.text=[array2 objectAtIndex:indexPath.row];
try this:-
NSDictionary *dict =[values valueForKey:#"rates"];
NSString *str=[dict valueForKey:#"amc"];
You need to do this:-
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
self.responseData = nil;
values = [responseString JSONValue];
NSMutableArray *arrTitle = [[NSMutableArray alloc] init];
NSMutableArray *arrValues = [[NSMutableArray alloc] init];
NSDictionary *dict =[values valueForKey:#"rates"];
NSString *str=[dict valueForKey:#"amc"];
rest you can do according to your requirements.
Return type for [values valueForKey:#"rates"] is a dictionary not array of values.
NSDictionary *dict = [values valueForKey:#"rates"];
Now you can refer get values within dictionary using objectForKey
Or else if you want to store in array.
NSMutableArray *array = [NSMutableArray array];
for (NSString *key in [dict allKeys])
{
array = [dict objectForKey:key];
}
So finally array has all the values within dictionary.
// returns no of rows
-(NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section
{
return [array count];
}
// contents of row will be
-(UITableViewCell*) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
{
static NSString *CellIdentifier = #"test";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSString *value = [self. array objectAtIndex:indexPath.row];
cell.textLabel.text = value;
return cell;
}

Three20 titleForHeaderInSection

Here is what I added. It just lists all the objectsForCharacters under each one of the alphabet characters.
- (void)tableViewDidLoadModel:(UITableView*)tableView {
items = [[NSMutableArray alloc] init];
arrayOfCharacters = [[NSMutableArray alloc]init];
objectsForCharacters = [[NSMutableDictionary alloc]init];
NSMutableArray *arrayOfNames = [[NSMutableArray alloc]init];
for (Kid_CareAppDelegate_City* post in _searchFeedModel.posts) {
[arrayOfNames addObject:post.city];
[items addObject:[TTTableTextItem itemWithText:post.city
URL:[NSString stringWithFormat:#"tt://city?to=%#",[post.city stringByReplacingOccurrencesOfString:#" " withString:#"+"]]]];
}
for(char c='A';c<='Z';c++){
[arrayOfCharacters addObject:[NSString stringWithFormat:#"%c",c]];
[objectsForCharacters setObject:arrayOfNames forKey:[NSString stringWithFormat:#"%c",c]];
}
NSLog(#"Array %#",arrayOfCharacters);
NSLog(#"Dict %#",objectsForCharacters);
TT_RELEASE_SAFELY(arrayOfNames);
self.items = items;
TT_RELEASE_SAFELY(items);
}
you can check out the link.http://blog.webscale.co.in/?p=240

Obj-C, iOS, can someone explain this NSMutableArray code and suggest how I can sort on the name?

Can someone exlain this code in detail and suggest how I can sort on the name?
- (void)handleSearchForTerm:(NSString *)searchTerm {
selectButton.enabled = NO;
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.keys) {
NSMutableArray *array = [Categories valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array) {
if ([name rangeOfString:searchTerm
options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.keys removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[table reloadData];
}
- (void)handleSearchForTerm:(NSString *)searchTerm {
selectButton.enabled = NO;
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init]; //creating an mutable array, which can be altered in progress.
[self resetSearch]; //calling some other method not displayed in the code here
for (NSString *key in self.keys) { //for each key,
NSMutableArray *array = [Categories valueForKey:key]; //you get the key's category
NSMutableArray *toRemove = [[NSMutableArray alloc] init]; //and initialize the array for items you wish to remove
for (NSString *name in array) { //then, for each name
if ([name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
//you check if the name is in range of the searchterm, with which you call this function
//if you don't find it, you add it to the removal list
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key]; //if you haven't found any name, it means you've added all the names in the toRemove array
[array removeObjectsInArray:toRemove]; //that means the count of both arrays are the same
[toRemove release]; //so you remove that section entirely, since there is no result there
}
[self.keys removeObjectsInArray:sectionsToRemove]; //you remove all the keys which aren't found
[sectionsToRemove release]; //leaving you the keys which are found
[table reloadData]; //you reload the table with the found results only
}
I hope it all made sense, I did my best commenting it ;)
Good luck.

Memory leak in NSMutableArray, NSArray, NSString in iPhone SDK

In my app, I got Memory leaks in NSMutableArray, NSArray and NSString.
Here is the code.
NSString *subQuery = [NSString stringWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease];
[subArray addObjectsFromArray:subArray1];
NSString *columnQuery = [NSString stringWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease];
[langArray addObjectsFromArray:newArray];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:[NSString stringWithFormat:#"%#",lblshortName.text]];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[tempArray addObject:[NSString stringWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
}
else {
[tempArray addObject:#"<empty>"];
}
NSString *detail = #"_________________";
for (int j=0; j<[lableNameArray count]; j++) {
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:[NSString stringWithFormat:#"%#",[lableNameArray objectAtIndex:j]]];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
detail = [NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4];
}
}
[detailTextArray addObject:detail];
}
When I run in Instruments I got leaks in
-subArray1 in second line.
-detail (NSString) in second for loop.
And subArray and langArray are my global arrays.
If I remove mutableCopy from NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; and NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease]; then subArray and langArray doesnot retain values.
How to avoid memory leak in this code?
Olease try this one, in above code you are creating two many objects that belong to autorelease pool here is one version where I tried to handle release of those string variables.
Second this is that the leak of detail is because you are de-referencing it many times in your code. And for subArray1 please see the comment
NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
// please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ;
[subArray addObjectsFromArray:subArray1];
[subQuery release];
NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ;
[langArray addObjectsFromArray:newArray];
[columnQuery relese];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:#"%#",lblshortName.text]];
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey];
[tempKey release];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
[tempArray addObject:tempString];
[tempString release];
}
else {
[tempArray addObject:#"<empty>"];
}
NSMutableString *detail = nil;
for (int j=0; j<[lableNameArray count]; j++)
{
detail = [[ NSMutableString alloc]initWithString:#"_________________"];
NSMutableString *key = [[NSMutableString alloc]initWithFormat:#"%#",[lableNameArray objectAtIndex:j]];
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key];
[key release];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail setString:[NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
}
[detailTextArray addObject:detail];
[detail release];
}
}
[subArray1 release];
[newArray release];
UPDATE : Please do read comments in the code and reply back so that things could be improved.
NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
//*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ;
[subArray addObjectsFromArray:subArray1];
[subQuery release];
NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
//*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ;
[langArray addObjectsFromArray:newArray];
[columnQuery relese];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:#"%#",lblshortName.text]];
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey];
[tempKey release];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
[tempArray addObject:tempString];
[tempString release];
}
else {
[tempArray addObject:#"<empty>"];
}
NSMutableString *detail = [[ NSMutableString alloc]initWithString:#"_________________"];
for (int j=0; j<[lableNameArray count]; j++)
{
NSMutableString *key = [[NSMutableString alloc]initWithFormat:#"%#",[lableNameArray objectAtIndex:j]];
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key]; //also here if you note you are using subArray1 not subArray?
[key release];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail setString:[NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
break;//I am not sure why you are checking this condition but assume that you want to get NOT NULL VALUE and add it to array?
}
}
[detailTextArray addObject:detail];
[detail release];
}
[subArray1 release];
[newArray release];
UPDATE 2:
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail appendFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
}
Thanks,
Not sure what is causing the memory leak, but this may help. This is a more direct way of copying the arrays, and may result in avoiding the leak:
NSArray *langArray =[[NSArray alloc] initWithArray: [self returnExecuteQuery:columnQuery] copyItems: YES];
This basically makes a one-level deep copy of the array returned by returnExecuteQuery. You can read about it in more detail in Collections Programming Topics.
I'm not sure how mutableCopy works and that may have something to do with the leak. If it copies the objects in the old array & then adds them to the new array, they may enter the array with a retain count of 2 (1 from the copy, and 1 from being added to an array.) It doesn't make much sense that it should work this way. But, if it does, that could account for the leak.
You could start by releasing your tempArray once done with it (after the loops).
Often, the higher levels leaks are hidden in the flood of lower level ones (ie a container leaking causes all its content to be leaked as well), which might be the case for your string.
Using mutableCopy] autorelease]; is fine by the way.

how to remove duplicate value in NSMutableArray

i'm scanning wifi info using NSMutableArray, but there are few duplicate values appear, so i try to use following code but still getting the duplicate values,
if([scan_networks count] > 0)
{
NSArray *uniqueNetwork = [[NSMutableArray alloc] initWithArray:[[NSSet setWithArray:scan_networks] allObjects]];
[scan_networks removeAllObjects];
NSSortDescriptor *networkName = [[[NSSortDescriptor alloc] initWithKey:#"SSID_STR" ascending:YES] autorelease];
NSArray *descriptors = [NSArray arrayWithObjects:networkName,nil];
[scan_networks addObjectsFromArray:[uniqueNetwork sortedArrayUsingDescriptors:descriptors]];
}
how this can be resolve, thanks
You can use NSSET but if you it is only used when order doesn't matter if order matter then go for this approach.I have used it and it give perfect answer. in Place of NSmutableArray array put your NSmutableArray which contains duplicate Value.
NSArray *copy = [NSmutableArray copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator])
{
if ([NSmutableArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound)
{
[NSmutableArray removeObjectAtIndex:index];
}
index--;
}
[copy release];
You should be using an NSMutableSet in the first place.
For eliminating all double entries in an array, see this question:
Make NSMutableArray or NSMutableSet unique.
Here is the code of removing duplicates values from NSMutable Array..it will work for you.
myArray is your Mutable Array that you want to remove duplicates values..
for(int j = 0; j < [myArray count]; j++){
for( k = j+1;k < [myArray count];k++){
NSString *str1 = [myArray objectAtIndex:j];
NSString *str2 = [myArray objectAtIndex:k];
if([str1 isEqualToString:str2])
[myArray removeObjectAtIndex:k];
}
}
// Now print your array and
I think its better to do this:
NSMutableIndexSet *indexes = [[NSMutableIndexSet alloc]init];
for(int j = 0; j < [myArray count]; j++) {
for( k = j+1;k < [myArray count];k++) {
NSString *str1 = [myArray objectAtIndex:j];
NSString *str2 = [myArray objectAtIndex:k];
if([str1 isEqualToString:str2])
[indexes addIndex:k];
}
}
[myArray removeObjectsAtIndexes:indexes];
You can run into problems if you manipulate the array while looping in my experience.
This is another way:
- (NSArray *)removeDuplicatesFrom:(NSArray *)array {
NSSet *set = [NSSet setWithArray:array];
return [set allObjects];
}
maybe you can try the NSArray category.
#import <Foundation/Foundation.h>
#interface NSArray(filterRepeat)
-(NSArray *)filterRepeat;
#end
#import "NSArray+repeat.h"
#implementation NSArray(filterRepeat)
-(NSArray *)filterRepeat
{
NSMutableArray * resultArray =[NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (![resultArray containsObject: obj]) {
[resultArray addObject: obj];
}
}];
return resultArray;
}
#end