Search in iOS for custom objects - ios

I am working on a custom contact,currently i'm using this code to search custom objects
filteredTableData = [[NSMutableArray alloc] init];
for (int i=0; i<contactSectionTitles.count; i++)
{
NSString *sectionTitle = [contactSectionTitles objectAtIndex:i];
NSArray *sectionmContacts = [mContacts objectForKey:sectionTitle];
for (CS_ContactDTO *theDto in sectionmContacts) {
NSRange nameRange = [theDto.mFirstName rangeOfString:text options:NSForcedOrderingSearch];
NSRange descriptionRange = [[theDto.mFirstName description] rangeOfString:text options:NSForcedOrderingSearch];
if(nameRange.location != NSNotFound || descriptionRange.location != NSNotFound)
{
if (![filteredTableData containsObject:theDto])//Search DTO
{
[filteredTableData addObject:theDto];
}
}
}
}
Note
"theDTO" is my custom class
It has values FirstName,LastName,PhoneNumber.
The code gives me result like,
For "A" -> "Arun","India","Kumar"
My requirement is like to search
"A" should provide only "Arun"(starting letter matching),not the other results.

Simply change your check to see if the range location is 0:
if (nameRange.location == 0 || descriptionRange.location == 0) {
This will be true if text is at the start of the name or description.
BTW - why do you check both mFirstName and mFirstName description? What's the difference?

If you want to check if NSString starts with a particular search term, you can use
if ([myString hasPrefix:#"searchTerm"])

Related

How to get native keyboard autosuggestion string value

I made a page which contained a UITextFiled and a view that presented search result and I want to change the triggering conditions of the search. The original triggering conditions was changing the input text of textField and I want to make some change. I hope the search is triggered only when user touch the keyboard autocorrection. Could someone give me some advance, thank you!
Try implementing UITextChecker like this. The last two lines are the print statement for two types. One is for guesses words when misspelled occurred and the other is for dictionary words. The arrPredectiveText array contains words sequentially like dictionary. You can get suggestions from this.
Call the suggestionsForCustomKeyboard method with some string that you are typing.
-(void)suggestionsForCustomKeyboard:(NSString *)word{
if ([currentString length] >= 1) {
UITextChecker *textChecker = [[UITextChecker alloc] init];
NSRange misspelledRange = [textChecker
rangeOfMisspelledWordInString:currentString
range:NSMakeRange(0, [currentString length])
startingAt:0
wrap:NO
language:#"en_US"];
if (misspelledRange.location != NSNotFound) {
guesses = [textChecker guessesForWordRange:misspelledRange
inString:currentString
language:#"en_US"];
NSLog(#"First guess: %#", [guesses firstObject]);
} else {
NSLog(#"Textchecker Not found");
autocorrectedText = #"";
}
if (arrPredectiveText.count >= 2){
suggestionOne = [arrPredectiveText objectAtIndex:0];
suggestionTwo = [arrPredectiveText objectAtIndex:1];
}
else if (arrPredectiveText.count == 1 && guesses.count >= 1) {
suggestionOne = [arrPredectiveText firstObject];
suggestionTwo = [guesses firstObject];
}else if (arrPredectiveText.count == 0 && guesses.count > 0){
suggestionOne = [guesses firstObject];
if (guesses.count > 1) {
suggestionTwo = [guesses objectAtIndex:1];
}
}
NSLog(#"Textchecker all guess: %#", guesses);
NSLog(#"Prediction: %#",arrPredectiveText);
}

Check if string is already exist and add a number as suffix to the string in the array?

I have a name as "Ryan" and next time entering "Ryan" it should check it has the value,So it should make it "Ryan_1". The same way it should check if anytime someone added again "Ryan" it should change it to "Ryan_2".
Example:
nameArray = ["Ryan","John","Ryan_2","Rhonda","Ryan_3","Kylie","Ryan_4","John_2"];
I am using below code which is working fine while adding the name first time.
But when I am coming back to the section and editing value Ex: I changed Ryan_2 to "xyz" and again thought of keeping "Ryan" the saved value is becoming "Ryan_4" where as it supposed to be "Ryan_2" in the array. And let say if I am changing "Ryan_4" to "somenewName" now the numbering of other duplicate names also get rearranged.
NSMutableArray *array = [[NSMutableArray alloc]init];
int occurrences = 0;
for(NSString *string in nameArray) {
if ([value isKindOfClass:[NSString class]]) {
if ([string containsString:value]) {
[array addObject:string];
}
occurrences+= ([string containsString:value] ? 1 : 0);
}
}
if ([value isKindOfClass:[NSString class]]) {
if (![value isEqualToString:#""]) {
if (occurrences > 1) {
value = [value stringByAppendingFormat:#"_%d", occurrences];
}
}
}
I would recommend an extension like this:
extension NSMutableArray {
public func appendWithSuffix(strNewEntry:String) {
var n = 1
var new = strNewEntry
if self.containsObject(strNewEntry) {
new = strNewEntry + "_\(n)"
while self.containsObject( new ){
n += 1
new = strNewEntry + "_\(n)"
}
}
self.addObject( new )
}}
It will look for an exact match and insert if none is found, i.e it will add "Ryan_5" instead of "Ryan", "John_3" instead of "John" and so on.
Another approach may be to iterate thru all entries for comparison or filter the array with "namexy".hasPrefix("Ryan") to get max index of name to be inserted.
- (IBAction)SaveText:(id)sender
{
if (array.count==0)
{
[array addObject:_txtAddText.text];
}else
{
for(NSString *string in array)
{
if ([string containsString:_txtAddText.text] )
{
count = count+1;
NSString *Localstring =[NSString stringWithFormat:#"%#%d",[string stringByAppendingString:#"_"],count];
NSLog(#"%#",Localstring);
[array addObject:Localstring];
break;
}else
{
[array addObject:_txtAddText.text];
}
}
}
NSLog(#"%#",array);
}

In my iPhone app,i am trying to implement a UISearchBar in Tableview

when search value from array am getting <__NSArrayM:> was mutated while being enumerated. Am using this code.
NSInteger strlen=[searchText length];
for (NSString *pStr in pArrBusinessName ) {
NSRange nameRange = [pStr rangeOfString:searchText options:NSCaseInsensitivePredicateOption];
if(nameRange.location != NSNotFound) {
if (strlen == 1) {
pArrFilteredTableData = pArrBusinessName;
} else {
if ([pStr isKindOfClass:[NSNull class]]) {
NSLog(#"NSNull isKindOfClass called!");
}
if (![pStr isKindOfClass:[NSNull class]]) {
[pArrFilteredTableData addObject:pStr];
}
}
} else {
if ([pArrFilteredTableData count] == 0) {
}
}
[pTblDetails reloadData];
}
Change this code:
pArrFilteredTableData = pArrBusinessName;
To this;
pArrFilteredTableData = [pArrBusinessName mutableCopy];
make sure pArrFilteredTableData is a NSMutableArray if it wasn't already
It seems to be that you are doing modifications in the main array while searching the contents inside it. It would be good if you hold your search results in a separate mutable array rather than mutating the main array using which you created your list. Filter searched records from the main array and hold them in search array.

When i click on map its get crashed at the initial time in iOS5?

for (int i = 0; i< [delarsInfoArray count] ; i++)
{
NSString *lattitudeValue;
NSString *longitudeValue;
if ([[delarsInfoArray objectAtIndex:i]count]>1) {
lattitudeValue = [[[delarsInfoArray objectAtIndex:i]valueForKey:#"LATITUDE"]objectAtIndex:1];
longitudeValue = [[[delarsInfoArray objectAtIndex:i]valueForKey:#"LONGITUDE"]objectAtIndex:0];
}
else
{
lattitudeValue = #"";
longitudeValue = #"";
}
CLLocationCoordinate2D pinLocation;
if(([lattitudeValue floatValue] != 0) && ([longitudeValue floatValue] != 0) ) {
mapRegion.center.latitude = [lattitudeValue floatValue];
mapRegion.center.longitude = [longitudeValue floatValue];
if(pinLocation.latitude !=0 && pinLocation.longitude !=0) {
myAnnotation1 = [[MyAnnotation alloc] init];
if ([[delarsInfoArray objectAtIndex:i] count] == 0) {
myAnnotation1.title = #"";
myAnnotation1.subtitle = #"";
}
else
{
// NSLog(#"====== delears array is===%#",delarsInfoArray);
NSLog(#"===== delears array count is %d",[delarsInfoArray count]);
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"Address"]objectAtIndex:2] !=nil)
{
myAnnotation1.title = [[[delarsInfoArray objectAtIndex:i]valueForKey:#"Address"]objectAtIndex:2];
}
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"City"]objectAtIndex:3]!= nil) {
myAnnotation1.subtitle = [[[delarsInfoArray objectAtIndex:i]valueForKey:#"City"]objectAtIndex:3];
}
NSLog(#"%#",[[[delarsInfoArray objectAtIndex:i]valueForKey:#"City"]objectAtIndex:3]);
}
[dealerMapView setRegion:mapRegion animated:YES];
[dealerMapView addAnnotation:myAnnotation1];
myAnnotation1.coordinate = mapRegion.center;
[myAnnotation1 release];
}
}
}
The above code is written in the viewWillAppear.After loading the map in to the view,when i clicked on the map.app gets crashed.How can solve this crash?
There are a lot of issues here, but the one that leaps out to the top of the list are the lines that read:
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"Address"]objectAtIndex:2] !=nil)
...
and
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"City"]objectAtIndex:3]!= nil) {
...
The problem is that objectAtIndex of a valueForKey of an array will never be nil. You can't store a nil in an array, so what valueForKey does, if it doesn't find a value, is it uses a NSNull object, [NSNull null]. That designates that there was no value found, but uses NSNull (which can be added to the array) instead of nil (which can't).
The problem is likely that there is some subsequent code (for example, the code that tries to figure out the size of the callout bubble) which tries to get the length of the string, but since you stored a NSNull, it's trying to call the length method and it's failing.
You could fix this a number of ways, such as:
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"Address"]objectAtIndex:2] != [NSNull null])
...

Search display controller iOS results disappear then reappear between words

I am searching my products like the below. It works fine however when searching between 2 words the results disappear then reappear once the user has entered the first character of the next word. i.e if I search "td pro" or "pro td" the results are there. If I search like this td(i have a result) td(space) I have NO result td p(I have a result) just to add I need to separate the words by space in componentsSeperatedByString because the user may not search for a product in any particular order. Unless there is a better method?
Here is my code:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
for (XMLStringFile *new in rssOutputData_MutableArray)
{
//Product scope
if ([scope isEqualToString:#"Product"])
{
// Split into search text into separate "words"
NSArray * searchComponents = [searchText componentsSeparatedByString: #" "];
;
BOOL foundSearchText = YES;
// Check each word to see if it was found
for (NSString * searchComponent in searchComponents) {
NSRange result = [new.xmlItem rangeOfString:searchComponent options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
NSRange descriptionRange = [new.xmlDescription rangeOfString:searchComponent options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
foundSearchText &= (result.location != NSNotFound|| descriptionRange.location != NSNotFound);
}
// If all search words found, add to the array
if (foundSearchText)
{
[self.filteredListContent addObject: new];
}
}
}
}
Many thanks
I fixed it with the help of another stack question that someone helped me with.
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
for (XMLStringFile *new in rssOutputData_MutableArray)
{
//Product scope
if ([scope isEqualToString:#"Product"])
{
// Split into search text into separate "words"
NSArray * searchComponents = [searchText componentsSeparatedByString: #" "];
//Before searching trim off the whitespace
searchText = [searchText stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
BOOL foundSearchText = YES;
// Check each word to see if it was found
for (NSString * searchComponent in searchComponents) {
NSRange result = [new.xmlItem rangeOfString:searchComponent options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
NSRange descriptionRange = [new.xmlDescription rangeOfString:searchComponent options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
foundSearchText &= (result.location != NSNotFound|| descriptionRange.location != NSNotFound);
}
// If all search words found, add to the array
if (foundSearchText)
{
[self.filteredListContent addObject: new];
}
}
}
}
The winning line is:
//Before searching trim off the whitespace
searchText = [searchText stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];

Resources