Below UITextChecker Function Is Not Working Properly - ios

NSString * currentWord;
currentWord = Text.text;
UITextChecker* checker = [[UITextChecker alloc] init];
NSString* preferredLanguage = [[UITextChecker availableLanguages] objectAtIndex:0];
NSRange range;
range = [checker rangeOfMisspelledWordInString:currentWord
range:NSMakeRange(0, [currentWord length])
startingAt:0
wrap:NO
language:preferredLanguage];
if (range.location == NSNotFound)
{
NSLog(#"Word found");
}
else
{
NSLog(#"Word not found");
}
//Here i used UITextChecker Function ,even for the wrong word, the above function shows correct word statement
eg: wrong word like abcd,
bcde,
cdef,
CAPs, kindly help me what is the reason behind this. Is there any other option to solve this?
Thanks in advance

UITextChecker *Checker = [[UITextChecker alloc] init];
NSRange range = NSMakeRange(0, inputWord.length);
NSRange misspelledRange = [Checker rangeOfMisspelledWordInString:[Sentence lowercaseString] range:range startingAt:0 wrap:NO language:#"en_IN"];
bool isValidWord = misspelledRange.location == NSNotFound;
//NSLog(#"----%i", misspelledRange.location);
if (isValidWord)
{
isValidWord = [self checkIfWordExistsInSuggestedSpellings:Sentence];
NSLog(#"++++%d", isValidWord);
}
return isValidWord;
}
else
{
NSLog(#"Invalid word");
return false;
}

NSNotFound means that whatever you asked for wasn't found. == is equality operator. Your code prints "Word found" when range.location is equal to NSNotFound.

Related

Regular Expression and NSAttributedString to change colour of all the same words UILabel [duplicate]

There is a substring that occurs in a string several times. I use rangeOfString, but it seems that it can only find the first location. How can I find all the locations of the substring?
NSString *subString1 = #"</content>";
NSString *subString2 = #"--\n";
NSRange range1 = [newresults rangeOfString:subString1];
NSRange range2 = [newresults rangeOfString:subString2];
int location1 = range1.location;
int location2 = range2.location;
NSLog(#"%i",location1);
NSLog(#"%i",location2);
You can use rangeOfString:options:range: and set the third argument to be beyond the range of the first occurrence. For example, you can do something like this:
NSRange searchRange = NSMakeRange(0,string.length);
NSRange foundRange;
while (searchRange.location < string.length) {
searchRange.length = string.length-searchRange.location;
foundRange = [string rangeOfString:substring options:0 range:searchRange];
if (foundRange.location != NSNotFound) {
// found an occurrence of the substring! do stuff here
searchRange.location = foundRange.location+foundRange.length;
} else {
// no more substring to find
break;
}
}
Swift 3.0
Find all locations of substring i
let text = "This is the text and i want to replace something"
let mutableAttributedString = NSMutableAttributedString(string: text)
var searchRange = NSRange(location: 0, length: text.characters.count)
var foundRange = NSRange()
while searchRange.location < text.characters.count {
searchRange.length = text.characters.count - searchRange.location
foundRange = (text as NSString).range(of: "i", options: NSString.CompareOptions.caseInsensitive, range: searchRange)
if foundRange.location != NSNotFound {
// found an occurrence of the substring! do stuff here
searchRange.location = foundRange.location + foundRange.length
mutableAttributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: foundRange)
}
else {
// no more substring to find
break
}
}
//Apply
textLabel.attributedText = mutableAttributedString;
And this output-
This is my solution. Basically, the algorithm traverses the string looking for substring matches and returns those matches in an array.
Since an NSRange is a struct it cannot be added to the array directly. By using NSValue, I can encode the match first and then add it to the array. To retrieve the range, I then decode the NSValue object to an NSRange.
#import <Foundation/Foundation.h>
NSRange makeRangeFromIndex(NSUInteger index, NSUInteger length) {
return NSMakeRange(index, length - index);
}
NSArray<NSValue *> * allLocationsOfStringMatchingSubstring(NSString *text, NSString *pattern) {
NSMutableArray *matchingRanges = [NSMutableArray new];
NSUInteger textLength = text.length;
NSRange match = makeRangeFromIndex(0, textLength);
while(match.location != NSNotFound) {
match = [text rangeOfString:pattern options:0L range:match];
if (match.location != NSNotFound) {
NSValue *value = [NSValue value:&match withObjCType:#encode(NSRange)];
[matchingRanges addObject:value];
match = makeRangeFromIndex(match.location + 1, textLength);
}
}
return [matchingRanges copy];
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSString *text = #"TATACCATGGGCCATCATCATCATCATCATCATCATCATCATCACAG";
NSString *pattern = #"CAT";
NSArray<NSValue *> *matches = allLocationsOfStringMatchingSubstring(text, pattern);
NSLog(#"Text: %#", text);
NSLog(#"Pattern: %#", pattern);
NSLog(#"Number of matches found: %li", matches.count);
[matches enumerateObjectsUsingBlock:^(NSValue *obj, NSUInteger idx, BOOL *stop) {
NSRange match;
[obj getValue:&match];
NSLog(#" Match found at index: %li", match.location);
}];
}
return 0;
}
Passing nil to [string rangeOfString:substring options:nil range:searchRange]; shows a warning.
To get rid of the warning, put in an enum from this group
enum {
NSCaseInsensitiveSearch = 1,
NSLiteralSearch = 2,
NSBackwardsSearch = 4,
NSAnchoredSearch = 8,
NSNumericSearch = 64,
NSDiacriticInsensitiveSearch = 128,
NSWidthInsensitiveSearch = 256,
NSForcedOrderingSearch = 512,
NSRegularExpressionSearch = 1024
};
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/index.html#//apple_ref/doc/constant_group/Search_and_Comparison_Options
Here is a version in Swift 2.2 of PengOne's answer with input from kevinlawler and Gibtang
Note: string and substring are of type NSString
let fullStringLength = (string as String).characters.count
var searchRange = NSMakeRange(0, fullStringLength)
while searchRange.location < fullStringLength {
searchRange.length = fullStringLength - searchRange.location
let foundRange = string.rangeOfString(substring as String, options: .CaseInsensitiveSearch, range: searchRange)
if foundRange.location != NSNotFound {
// found an occurrence of the substring! do stuff here
searchRange.location = foundRange.location + 1
} else {
// no more strings to find
break
}
}
I suggest using regular expression because it's a more declarative way and has fewer lines of code to write.
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"%#" options:nil error:nil];
NSString *toSearchStr = #"12312 %# Text %# asdsa %#";
__block int occurs = 0;
[regex enumerateMatchesInString:toSearchStr options:0 range:NSMakeRange(0, toSearchStr.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
occurs++;
}];
// occurs == 3

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 one String contains the same characters as another string

I am trying to write a function which will allow me to determine whether one NSString* contains the characters of another NSString*. As an example, refer to the below scenario:
NSString *s1 = #"going";
NSString *s2 = #"ievngcogdl";
So essentially when the comparison between these 2 strings occurs, it should return true as the first string s1 has the same characters of the second string s2. Could I use an NSCountedSet? I know that this class has a method containsObject:(id) although I don't think that will solve my problem. Is there any other ways in completing this function and provide me the required results?
I think this method could be rather slow, but I would still favour it over [NSString rangeOfCharacterFromSet:], which requires creating an NSCharacterSet object per comparison:
- (BOOL)string:(NSString *)string containsAllCharactersInString:(NSString *)charString {
NSUInteger stringLen = [string length];
NSUInteger charStringLen = [charString length];
for (NSUInteger i = 0; i < charStringLen; i++) {
unichar c = [charString characterAtIndex:i];
BOOL found = NO;
for (NSUInteger j = 0; j < stringLen && !found; j++)
found = [string characterAtIndex:j] == c;
if (!found)
return NO;
}
return YES;
}
This will work -
-(BOOL) string:(NSString *)string1 containsInputString:(NSString *)string2 {
// Build a set of characters in the string
NSCountedSet *string1Set = [[NSCountedSet alloc]init];
[string1 enumerateSubstringsInRange:NSMakeRange(0, string1.length)
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[string1Set addObject:substring];
}];
// Now iterated over string 2, removing characters from the counted set as we go
for (int i=0;i<string2.length;i++) {
NSRange range = [string2 rangeOfComposedCharacterSequenceAtIndex:i];
NSString *substring = [string2 substringWithRange:range];
if ([string1Set countForObject:substring]> 0) {
[string1Set removeObject:substring];
}
else {
return NO;
}
}
return YES;
}
Regular Expressions are the best way to check this type of conditions and check this link once
Below I am adding the code for your solution, please check once
NSString *s1 = #"going"
NSString *s2 = #"ievngcogdl";
if ([self string:s1 containsSameCharacterofString:s2]) {
NSLog(#"YES");
}
- (BOOL)string:(NSString *)str containsSameCharacterofString:(NSString *)charString
{
if (charString.length >= str.length) {
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:#"^[%#]+$", charString] options:NSRegularExpressionCaseInsensitive error:&error];
NSRange textRange = NSMakeRange(0, str.length);
NSRange matchRange = [regex rangeOfFirstMatchInString:str options:NSMatchingReportProgress range:textRange];
return (matchRange.location != NSNotFound);
}
else {
return NO;
}
}
BOOL containsString = [#"Hello" containsString:#"llo"];
if (containsString) {
// Do Stuff
}

iphone sdk : Break chinese sentence into words and letters

I have Chinese news feed and I want to break the sentence into smaller chunks to pass to the API.
How can I do it in ios? I have set character length of 50 characters for English language.
Currently I am using rangeOfString: function to find dot, comma and break into sentence.
NSString *str = nil, *rem = nil;
str = [final substringToIndex:MAX_CHAR_Private];
rem = [final substringFromIndex:MAX_CHAR_Private];
NSRange rng = [rem rangeOfString:#"?"];
if (rng.location == NSNotFound) {
rng = [rem rangeOfString:#"!"];
if (rng.location == NSNotFound) {
rng = [rem rangeOfString:#","];
if (rng.location == NSNotFound) {
rng = [rem rangeOfString:#"."];
if (rng.location == NSNotFound) {
rng = [rem rangeOfString:#" "];
}
}
}
}
if (rng.location+1 + MAX_CHAR_Private > MAXIMUM_LIMIT_Private) {
rng = [rem rangeOfString:#" "];
}
if (rng.location == NSNotFound) {
remaining = [[final substringFromIndex:MAX_CHAR_Private] retain];
}
else{
//NSRange rng = [rem rangeOfString:#" "];
str = [str stringByAppendingString:[rem substringToIndex:rng.location]];
remaining = [[final substringFromIndex:MAX_CHAR_Private + rng.location+1] retain];
}
This is not working correctly for chinese and japanese characters.
Check NSLinguisticTagger, It should work with Chinese:
From Apple: "The NSLinguisticTagger class is used to automatically segment natural-language text and tag it with information, such as parts of speech. It can also tag languages, scripts, stem forms of words, etc."
Apple documentation NSLinguisticTagger Class Reference
Also see NSHipster NSLinguisticTagger.
Also see objc.io issue 7
NSString provides that out of the box with NSStringEnumerationBySentences enumeration option:
[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
options:NSStringEnumerationBySentences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop)
{
NSString *sentence = [substring stringByTrimmingCharactersInSet:whiteSpaceSet];
// process sentence
}
];

Is there a way to work case insensitive with UITextChecker?

I need my app to check if a word entered by the user is actually a real word or not. For doing this i found the UITextChecker. I am using it to check for words like this:
UITextChecker *textChecker = [[UITextChecker alloc] init];
NSLocale *locale = [NSLocale currentLocale];
NSString *language = [locale objectForKey:NSLocaleLanguageCode];
NSRange searchRange = NSMakeRange(0, [currentWord length]);
NSRange misspelledRange = [textChecker rangeOfMisspelledWordInString:currentWord range: searchRange startingAt:0 wrap:NO language:language];
if (misspelledRange.location == NSNotFound) NSLog(#"is a word");
else NSLog(#"is not a word");
This works fine until it comes to words that begin with an uppercase (and that are a lot of words in german :) ). The user is entering the text lowercase, so even if a word is actually a word it outputs "is not a word" because of it being lowercase.
I found no solution for this problem in the documentation, also i searched for it here.
So my question is if there is any better way for doing this, than transforming the first letter into an uppercase if the check failed?
Example for what i would do if there is no other way:
NSRange misspelledRange = [textChecker rangeOfMisspelledWordInString:currentWord range: searchRange startingAt:0 wrap:NO language:language];
if (misspelledRange.location == NSNotFound) NSLog(#"is a word");
else {
NSString *firstLetter = [currentWord substringToIndex:1];
NSString *restWord = [currentWord substringFromIndex:1];
currentWord = [NSString stringWithFormat:#"%#%#", [firstLetter capitalizedString], restWord];
NSRange misspelledRange = [textChecker rangeOfMisspelledWordInString:currentWord range: searchRange startingAt:0 wrap:NO language:language];
if (misspelledRange.location == NSNotFound) NSLog(#"is a word");
NSLog(#"is not a word");
}
Thanks for your help!

Resources