UITextView Autocomplete modification - iphone

I'm currently using this HTAutocompleteTextField to fill in a UITextField with a predefined list, should A user start typing in an entry that already exists. There are a couple of problems that I've been having however. The first is that it seems to stop when a comma is typed in (but not apostrophes). I've been looking around and I'm really not sure why it's doing it. I thought at one point it could be that the comma was a different comma, like an apostrophe issue I had due to importing the list from a word document. However, it wasn't the case. The second issue is more of an addition which I'm not really sure how to implement. I also want the autosuggest to detect suggestions for words in mid string, not just from the beginning. So for instance typing in "String" would suggest "This is a String". This currently how it does the auto suggest, but I have no idea how to do the above things.
NSString *prefixLastComponent = [componentsString.lastObject stringByTrimmingCharactersInSet:space];
if (ignoreCase)
{
stringToLookFor = [prefixLastComponent lowercaseString];
}
else
{
stringToLookFor = prefixLastComponent;
}
for (NSString *stringFromReference in colorAutocompleteArray)
{
NSString *stringToCompare;
if (ignoreCase)
{
stringToCompare = [stringFromReference lowercaseString];
}
else
{
stringToCompare = stringFromReference;
}
if ([stringToCompare hasPrefix:stringToLookFor])
{
return [stringFromReference stringByReplacingCharactersInRange:[stringToCompare rangeOfString:stringToLookFor] withString:#""];
}
}
If anyone could give me any pointers on how to get this done, I'd appreciate it.
Regards,
Mike

Managed to go about solving both issues. For any one who uses this Git Repository, the reason why commas don't work when using the preset methods is because of NSArray *componentsString = [prefix componentsSeparatedByString:#","];. Remove the comma so it's NSArray *componentsString = [prefix componentsSeparatedByString:#""]; and it should work nicely. To fix the other problem where it only detects the start of words, I changed the methods a little. Here are my changes in HTAutocompleteManager.m
int i = 0;
for (NSString *stringFromReference in colorAutocompleteArray)
{
NSString *stringToCompare;
if (ignoreCase)
{
stringToCompare = [stringFromReference lowercaseString];
}
else
{
stringToCompare = stringFromReference;
}
if ([stringToCompare hasPrefix:stringToLookFor])
{
//NSLog(#"Removing String: %# atIndex: %d", [colorAutocompleteArray objectAtIndex:i], i);
[colorAutocompleteArray removeObjectAtIndex:i];
[colorAutocompleteArray insertObject:stringFromReference atIndex:0];
//NSLog(#"Adding String atIndex 0: %#", stringFromReference);
return [stringFromReference stringByReplacingCharactersInRange:[stringToCompare rangeOfString:stringToLookFor] withString:#""];
}
else if ([stringToCompare hasSuffix:stringToLookFor] && ([stringToLookFor length] >= 3)) {
return [NSString stringWithFormat:#" %#", stringFromReference];
}
else if (!([stringToCompare rangeOfString:stringToLookFor].location == NSNotFound) && ([stringToLookFor length] >= 3))
{
return [NSString stringWithFormat:#" %#", stringFromReference];
}
++i;
}
The reason for reordering the Array is because after the 3rd character is typed it will prioritise the other two if statements because they will be reached first if there is a generic term in multiple entries in the array (like "Street" in a list of locations). I know it's not necessary to have the "hasSuffix" if statement, but I left it in case someone wants to use it on it's own. Lastly, I added in a space before stringFromReference so that it doesn't look weird when there's a suggestion straight after the input text. When we exit the UITextField we remove this space like this (inside HTAutocompleteTextField.m - commitAutocompleteText):
NSString *currentText = self.text;
if ([self.autocompleteString isEqualToString:#""] == NO
&& self.autocompleteDisabled == NO)
{
if ([self.autocompleteString hasPrefix:#" "]) {
self.autocompleteString = [self.autocompleteString substringFromIndex:1];
}
self.text = [NSString stringWithFormat:#"%#", self.autocompleteString];
self.autocompleteString = #"";
[self updateAutocompleteLabel];
}
return ![currentText isEqualToString:self.text];
Hope this makes sense to anyone who's in a similar situation.
Mike

Related

iOS rangeOfString can't locate the string that is definitely there

I am writing code in objective-c. I would like to extract a url from a string.
Here is my code:
NSMutableString *oneContent = [[latestPosts objectAtIndex:i] objectForKey:#"content"];
NSLog(#"%#", oneContent);//no problem
NSString *string = #"http";
if ([oneContent rangeOfString:string].location == NSNotFound) {
NSLog(#"string does not contain substring");
} else {
NSLog(#"string contains substring!");
}
As you can see, I want to extract a url from the oneContent string, and I have checked that oneContent definitely contains "http", but why does the result show nothing?
Is there some better way to extract the url?
Check oneContent or the actual code you are running.
This works:
NSMutableString *oneContent = [#"asdhttpqwe" mutableCopy];
NSLog(#"%#", oneContent);//no problem
NSString *string = #"http";
if ([oneContent rangeOfString:string].location == NSNotFound) {
NSLog(#"string does not contain substring");
} else {
NSLog(#"string contains substring!");
}
NSLog output:
Untitled[5911:707] asdhttpqwe
Untitled[5911:707] string contains substring!
It is probably best not to use a Mutable string unless there is some substantial reason to do so.
I would suggest using NSScanner.

Deleting a number digit by digit on a calculator screen

I want to delete a number digit by digit on the calculator screen but am only being able to delete the full number . Is there any method ?
-(IBAction)cancelInput:(float)result1{
NSString *myString = [[NSNumber numberWithFloat:result] stringValue];
int str=[myString length]-1;
NSString *newstring = [[NSNumber numberWithInt:str] stringValue];
calculatorScreen.text= [NSString stringWithFormat:newstring];
//NSLog(#"%d ",str);
}
Here you go,
NSString *myString = [[NSNumber numberWithFloat:result] stringValue];
myString = [myString substringToIndex:[myString length]-1];
calculatorScreen.text= myString;
int str=[myString length]-1 will only return the length of your string, say if your number is 9876, it will return 3(4-1) and your newstring will be 3.If you want to delete the last character you have to create substring of myString.
string = [string substringToIndex:[string length] - 1];
-(IBAction)backPressed:(UIButton *)sender
{
self.display.text=[self.display.text substringToIndex:[self.display.text length]-1];
if ( [self.display.text isEqualToString:#""] || [self.display.text isEqualToString:#"-"])
{
self.display.text =#"0";
}
}
This is the core function for the button. I took the liberty to add in the if feature so that it could handle some of the basic issues. As usual, replace display with your primary label. The If function help to counter check that your label does not become empty " " or have a negative sign "-" and will automatically replace it with "0", similar to clear in that aspect. in which you can run the clear method instead. But use
self.display.text =#"0";
for better clarification instead.
Use this code for it:
else if([character isEqualToString:(NSString*) Delete])
{
NSInteger index_of_char_to_remove=[_display length]-1;
if(index_of_char_to_remove>=0)
{
[_display deleteCharactersInRange:NSMakeRange(index_of_char_to_remove, 1)];
last_character_is_operator=NO;
}
}
When press 'C' it will checked this condition and delete the data one by one

What is the shortest way to write rangeOfString with list of names, dictionary, king james bible, etc?

This is embarrassing. I don't want to use coredata or text file. I need shortest way to write this code.
names ("John", "Matthew", "thomas", "isaac", "bible", "Mayan", "2012", more names)
This code takes extremely long and wasting too much memory, download time, and waste of space. Not recommend it. 10,000 lines.
NSString *selectives = Name.text;
if ([selectives rangeOfString:#"John"].location != NSNotFound) {
//
}
if ([selectives rangeOfString:#"Matthew"].location != NSNotFound) {
//
}
Second. This code doesn't work. I don't what I'm doing wrong here. I'm lost. I need help!
NSString *string = Name.text;
NSString *NameMe = [NSString stringWithString:#"Jake", "miller", "thomas", "isaac"];
if([string rangeOfString:NameMe].location !=NSNotFound)
{
//
}
Is there a better way to write this? How do you write? I'm not good at this.
In the first case you can use fast enumeration to shorten your code.
NSArray *searchStrings = // Set up your search strings however you want
NSString *selectives = Name.text
for (NSString *searchString in searchStrings) {
if [selectives rangeOfString:searchString].location != NSNotFound {
// Your processing here
}
}
In the second case this line is wrong
NSString *NameMe = [NSString stringWithString:#"Jake", "miller", "thomas", "isaac"];
You aren't passing in a properly formed string. #"Jake" is valid, the rest, because they are outside the #"..." section are not.

Problem with NSRange

I'm having a problem with NSRange. Here is my code:
NSRange range = [[[NSHTTPCookie requestHeaderFieldsWithCookies:[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:cookie]]] objectForKey:#"Cookie"] rangeOfString:#"x"];
NSLog(#"%f", range.length);
if (range.length >= 1) {
NSLog(#"Do Something");
} else {
NSLog(#"AUTHING");
}
Console output:
0.000000
Do something
And then the second time I run through the code:
0.000000
AUTHING
What the hell is going on? NSNotFound I think it was does not work and I'm not the only person finding this problem so using it is not a solution.
Thanks for any help.
Cheers
Edit: I tried using NSLog(#"%d", range.length) but it gives incorrect output the first time it runs through, the second time it runs through it is correct. I've tried using NSNotFound thinking that the strange output is due to it being NSNotFound but it didn't trigger
If you want to see if the string was found using -[NSString rangeOfString:], you need to see if NSRange.location == NSNotFound:
if (range.location != NSNotFound) {
// String was found
else {
// String not found
}
As a general comment, debugging is much easier if you split up the nested method calls and do a quick NSLog to see what's going on. (i'm not that good at adhering to that so it's not meant as criticism).
One thing i first noted was the use of "%f" to display the length, try using %i (integer) and you should be able to get the correct length. %f will always display 0.00000.
what url are you using? given that you are pulling the data from the headers, the string "x" may or may not be present in the field. i would suggest NSLog-ing the NSString* object that you pull out of the dictionary and checking to see what's going on. E.g.:NSString *cookie = #"http://www.google.com/";
NSHTTPCookieStorage *store = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSURL *url = [NSURL URLWithString:cookie];
NSDictionary *header = [NSHTTPCookie requestHeaderFieldsWithCookies: [store cookiesForURL:url]];
NSString *cookieParameter = [header objectForKey:#"Cookie"];
NSLog(#"Cookie param is %#", cookieParameter);
// Test range of "x"
NSRange range = [cookieParameter rangeOfString:#"x"];
NSLog(#"%f", range.length); // will print out 0.00000
NSLog(#"%i", range.length); // will print out correct length (always 1 for "x")
NSLog(#"%i", range.location); // will print out the location of the first instance of "x"
if (range.length >= 1) {
NSLog(#"Do Something");
} else {
NSLog(#"AUTHING");
}
It seems like the code just detects the index of the string "x" from what I can tell, is this the intended result?

stringByReplacingCharactersInRange don't replace It's Append !

I Spent 5 hours try to figure a way for that..i'm trying to do a hangman app for iphone and the method below is the method that should be called when the player chooses a character and it match the chosen word..
-(void)replaceTheHiddenTextWithNewText:(NSString*)character{
NSString *fullTextField = fullText.text;
int textCount = [hiddenText.text length];
NSString *theRiddle;
for (int i = textCount-1 ; i>=0; i--) {
NSString *hiddenTextField = [[NSMutableString alloc] initWithString:hiddenText.text];
NSString *aChar=[fullTextField substringWithRange:NSMakeRange(i/3,1)];
if ([aChar isEqualToString:#" "]) {
theRiddle= [hiddenTextField stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:#" "];
}else if ([aChar isEqualToString:character]) {
theRiddle =[hiddenTextField stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:aChar];
}else{
theRiddle = [hiddenTextField stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:#"_"];
}
hiddenTextField = theRiddle;
}
hiddenText.text=theRiddle;
}
the problem is stringByReplacingCharactersInRange doesn't replace the character, it appends it to the underscore what am I doing wrong here?
Best Regards,
M Hegab
Just played around with your code. It does not work, but stringByReplacingCharactersInRange is not your problem.
Your game logic doesn't work like it should. Get a pen and a sheet of paper and "manually" loop through your for loop to see that this must be wrong.
Next time, if you've stared at code for half an hour, take a pen. This will save you at least 4 hours :-)
There are some issues with your code. Assume Kartoffelkäfer is the word you are looking for, and the user enters the letter f.
for (int i = textCount-1 ; i>=0; i--) {
NSString *hiddenTextField = [[NSMutableString alloc] initWithString:hiddenText.text];
// you are creating this string in every loop from the text of a (I guess) UITextField.
// I don't know what the content of this text is but I guess it is suppossed to be `______________`
// in every loop you replace the word where you replaced the _ with the correct letter with the string from the textfield.
// Btw, you are leaking this string.
NSString *aChar=[fullTextField substringWithRange:NSMakeRange(i/3,1)];
// Kartoffelkäfer has 14 chars so i is 13. And 13/3 is 4. And the character at index 4 is o
// In the next loop i is 12. And 12/3 is 4, too.
// next three loops will give you index 3. Then you get three times index 2, and so one.
// you never reach the letter f, anyway.
if ([aChar isEqualToString:#" "]) {
theRiddle= [hiddenTextField stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:#" "];
}else if ([aChar isEqualToString:character]) {
theRiddle =[hiddenTextField stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:aChar];
}else{
theRiddle = [hiddenTextField stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:#"_"];
// You should not replace a unmatched character with a _ . Because already matched letters would be overwritten.
}
hiddenTextField = theRiddle;
}
I assumed that the content of hiddenText.text is #"______"
and the content of fullText.text is #"Kartoffelkäfer". So hiddentext is the exact length as the fullText.
What I had to change to get this to work:
NSString *theRiddle;
NSString *hiddenTextField = [[[NSMutableString alloc] initWithString:hiddenText.text] autorelease];
for (int i = textCount-1 ; i>=0; i--) {
NSString *aChar=[fullTextField substringWithRange:NSMakeRange(i,1)];
if ([aChar isEqualToString:#" "]) {
theRiddle= [hiddenTextField stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:#" "];
}else if ([aChar isEqualToString:character]) {
theRiddle =[hiddenTextField stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:aChar];
}
else {
theRiddle = hiddenTextField;
}
hiddenTextField = theRiddle;
}
hiddenText.text=theRiddle;
Far away from good code, but I tried to change your code as little as possible.