Checking if a word is real - swift

I want to make sure that a word is real and this is my code:
var checker: UITextChecker = UITextChecker()
var range: NSRange = NSRange(location: 0,length: (count(completeWord)))
var misspelledRange: NSRange = checker.rangeOfMisspelledWordInString(completeWord, range: range, startingAt: 0, wrap: false, language: "en_US")
var isRealWord: Bool = misspelledRange.location == NSNotFound
if isRealWord {
println("Correct")
} else {
println("Not Correct")
}
But even if I give it a letter, it says correct. What can I do about that? Basically, I want to remove letters from the corrects.

UITextChecker gives you misspelled words in a sentence. It won't show you wrong letter in a word, but wrong word in the whole text input.
For example:
var checker: UITextChecker = UITextChecker()
let string:NSString = "Airplane is gren"
var range: NSRange = NSRange(location: 0,length: string.length)
var misspelledRange: NSRange = checker.rangeOfMisspelledWordInString(string as String, range: range, startingAt: 0, wrap: false, language: "en_US")
misspelledRange.toRange()
gives you result as 12..<16, i.e the whole word.
You could use guessesForWordRange to get possible correct substitutes:
let guesses = checker.guessesForWordRange(misspelledRange, inString: string as String, language: "en_US") as? [String]
(returns ["green", "greg", "grep", "grew", "grey", "gran", "grin", "glen", "aren", "oren", "wren"])

Related

TextKit 2: Applying ParagraphStyle in custom NSTextParagraph leads to cursor position being off

In a NSTextContentStorageDelegate I use textContentStorage(_ textContentStorage: NSTextContentStorage, textParagraphWith range: NSRange) -> NSTextParagraph? to serve custom NSTextParagraphs. In these I set a paragraph style to the attributed string. The head indent of this paragraph style equals the amount of whitespace at the beginning of the string. This leads to an aligned indent when the line is wrapped in the text view.
This works. However, in some cases (not always) the caret will not move to the end of the wrapped line. It is stuck before and does not reflect the correct insertion point, a bit like so:
xxx xx xx
xxx xx Ixx <- does not move to the last characters
I add the code below. Does anybody have an idea why this may happen? All help is greatly appreciated.
This is the code:
extension HighlightTextEditor.Coordinator : NSTextContentStorageDelegate{
func textContentStorage(_ textContentStorage: NSTextContentStorage, textParagraphWith range: NSRange) -> NSTextParagraph? {
var paragraphWithDisplayAttributes: NSTextParagraph? = nil
let textWithDisplayAttributes = textContentStorage.textStorage!.attributedSubstring(from: range)
var finalString: NSMutableAttributedString? = nil
if parent.lineBreakStrategy != .none{
var indentLength: CGFloat = 0
//find the first index which is not a whitespace
if let endIndex = textWithDisplayAttributes.string.firstIndex(where: {!$0.isWhitespace}){
if endIndex != textWithDisplayAttributes.string.startIndex{
//calculate a range from start to first non-whitespace character and convert to NSRange
let range: Range = textWithDisplayAttributes.string.startIndex..<endIndex
let convertedRange = NSRange(range, in: textWithDisplayAttributes.string)
//get a substring with only the whitespace characters
var measureString: NSAttributedString?
if parent.lineBreakStrategy == .aligned{
measureString = textWithDisplayAttributes.attributedSubstring(from: convertedRange)
} else if parent.lineBreakStrategy == .indented{
measureString = textWithDisplayAttributes.attributedSubstring(from: convertedRange) + NSAttributedString(string: " ")
}
//get the size of the substring and calcualte the index lengths depending on the strategy
indentLength = measureString?.size().width ?? 0
//create the paragraphStyle and set the headIndent either to the length or 0, if not calculated
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.headIndent = indentLength
//add the paragraphstyle to textWithDisplayAttributes
finalString = NSMutableAttributedString(attributedString: textWithDisplayAttributes)
if let finalString = finalString{
finalString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: finalString.length))
//create the new NSTextPara with the final string
paragraphWithDisplayAttributes = NSTextParagraph(attributedString: finalString)
}
}
}
}
return paragraphWithDisplayAttributes
}

Cannot spell check words of less than seven characters with UITextChecker

I'm attempting to check whether a word is in the dictionary with the following function
func isReal(word: String) -> Bool {
let checker = UITextChecker()
let range = NSRange(location: 0, length: word.utf16.count)
let wordRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en")
return wordRange.location == NSNotFound
}
The problem is that this only works correctly for words of seven characters or more. Shorter words return true even if they are not in the dictionary. Specifically, we get wordRange = {9223372036854775807, 0} in this case, the same as for a valid word.
The solution turns out to be embarrassingly simple. Our strings were upper case, and UITextChecker treats any upper case string shorter than seven characters as a possible valid acronym. In lower case everything works as expected.
I find it works just fine, when I use your function in a Swift Playground:
import UIKit
func isReal(word: String) -> Bool {
let checker = UITextChecker()
let range = NSRange(location: 0, length: word.utf16.count)
let wordRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en")
return wordRange.location == NSNotFound
}
let validStrings = ["test", "fest", "fast"]
let validResults = validStrings.map{ isReal(word:$0) }
print(validResults)
let invalidStrings = ["xt", "fxxx", "srwe"]
let invalidResults = invalidStrings.map{ isReal(word:$0) }
print(invalidResults)
Your issue may be platform or version specific.

how to find the range of exact word repeated in the string (case sensitive)

I want to find the nsrange of the the word which is repeating in the string ,it search should be case sensitive .
for example :
the main string is let str = "Hi satheesh how are you doing ,Hellow satheesh1 did you find the answer for satheesh".
now I want to find the ranges of word "satheesh" ..expected nsrange count should be 2 .i.e [nsrange(location : 3, lenght : 8),[nsrange(other word satheesh)] it should not take the range of satheesh1 because satheesh != satheesh1 .
I am using below code
extension String {
func ranges(of substring: String, options: CompareOptions = [], locale: Locale? = nil) -> [Range<Index>] {
var ranges: [Range<Index>] = []
while let range = self.range(of: substring, options: options, range: (ranges.last?.upperBound ?? self.startIndex)..<self.endIndex, locale: locale) {
ranges.append(range)
}
return ranges
}
}
but the problem with this code is when finding the range it considering satheesh == satheesh1 so I am getting the ranges of satheesh and satheesh.
Can some one help me out to solve this problem

Swift. Add attributes to multiple instances

I have arrays containing strings of the text terms to which I want to apply a particular attribute. Here's a code snippit:
static var bold = [String]()
static let boldAttribs = [NSFontAttributeName: UIFont(name: "WorkSans-Medium", size: 19)!]
for term in bold {
atStr.addAttributes(boldAttribs, range: string.rangeOfString(term))
}
This works great for single term or phrase use. But it only applies to the first use of a specific term. Is there a way, without resorting to numerical ranges, to apply the attribute to all instances of the same term? For example, make every use of "animation button" within the same string bold.
Edit: This works.
// `butt2` is [String]() of substrings to attribute
// `term` is String element in array, target of attributes
// `string` is complete NAString from data
// `atStr` is final
for term in butt2 {
var pos = NSRange(location: 0, length: string.length)
while true {
let next = string.rangeOfString(term, options: .LiteralSearch, range: pos)
if next.location == NSNotFound { break }
pos = NSRange(location: next.location+next.length, length: string.length-next.location-next.length)
atStr.addAttributes(butt2Attribs, range: next)
}
}
You don't have to resort to numerical ranges, but you do need to resort to a loop:
// atStr is mutable attributed string
// str is the input string
atStr.beginEditing()
var pos = NSRange(location: 0, length: atStr.length)
while true {
let next = atStr.rangeOfString(target, options: .LiteralSearch, range: pos)
if next.location == NSNotFound {
break
}
atStr.addAttributes(boldAttribs, range: next)
print(next)
pos = NSRange(location: next.location+next.length, length: atStr.length-next.location-next.length)
}
atStr.endEditing()

Find and replace multiple occurrences of a word in a long string

I'm parsing through some HTML files and tagging while I write the markdown.
For a simplified example:
var String = "This is a text <int=8-10, This is some more text.><int=1-7, This is some alt text.>"
Let's say for starters I want to match every <int= in this string and remove it. Is there an efficient way to do this in Swift right now?
myString.stringByReplacingOccurrencesOfString("<int=", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
stringByReplacingOccurrencesOfString (documentation) will replace a substring with another substring (in this case empty "").
Here is a method to get ranges of substrings as an array:
(
"NSRange: {538, 1}",
"NSRange: {848, 1}",
"NSRange: {1183, 1}",
"NSRange: {1418, 1}"
)
func rangesOfString(searchString: String, attrStr : NSMutableAttributedString) -> NSArray
{
var inputLength = count(attrStr.string)
var searchLength = count(searchString)
var range = NSRange(location: 0, length: attrStr.length)
var results = NSMutableArray()
while (range.location != NSNotFound) {
range = (attrStr.string as NSString).rangeOfString(searchString, options: nil, range: range)
if (range.location != NSNotFound) {
results.addObject(NSRange(location: range.location, length: searchLength))
range = NSRange(location: range.location + range.length, length: inputLength - (range.location + range.length))
}
}
return results as NSArray
}
For your information, this function is now called:
replacingOccurrences(of: String, with: String, options: String.CompareOptions, range: Range<String.Index>?)