在UITextView中获取当前键入的单词
我想在UITextView
获取当前键入的单词。 获取完全输入单词的方法可以在这里找到UITEXTVIEW:获取最近在uitextview中输入的单词,但是,我希望在输入时得到单词(无论在哪里输入, UITextView
开头,中间,结尾)。
我想定义一个单词的类型是一个空白字符后跟字母数字字符,或者如果当前位置(以某种方式用range.location
)是UITextView
的开头,那么后续的任何内容都应该被视为单词。 当另一个空格字符跟随时,将完成一个单词的输入。
我尝试过:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text`
但我找到正确的范围有问题。
简而言之:我需要在UITextView
找到子字符串,其中substring是当前键入的字。
编辑 :因为问题出现了。 我正在使用NSLayoutManager
并将NSLayoutManager
绑定到它,然后将其作为layoutManager传递给NSTextStorage
。
EDIT2 : (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
的主要问题(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
是指range.location
与指标不一样,但总是少1。 如果光标位于位置1,键入一个字母后, range.location
将返回0.有什么办法吗? 此外, UITextView
的text
属性似乎也是1。 当文本是foobar
并且我输出UITextView.text
然后我得到fooba
而不是。 因此range.location+1
返回exceptionRange {0, 1} out of bounds; string length 0'
Range {0, 1} out of bounds; string length 0'
编辑3 :也许用NSTextStorage
而不是UITextView
更容易获得我想要的结果?
UITextView委托方法: -textView:textView shouldChangeTextInRange:range replacementText:text
做的是它询问是否应该在-textView:textView shouldChangeTextInRange:range replacementText:text
的指定范围内的文本视图中替换指定的文本。
每次我们在将其更新到文本视图之前键入一个charactor时,都会调用此方法。 这就是为什么当你在range.location
中键入第一个字符时,你将range.location
为0。
只有当此方法的返回为真时, textView
才会更新我们在textView
输入的内容。
这是-textView:textView shouldChangeTextInRange:range replacementText:text
的参数定义-textView:textView shouldChangeTextInRange:range replacementText:text
apple提供的-textView:textView shouldChangeTextInRange:range replacementText:text
方法:
范围 : – 当前选择范围。 如果范围的长度为0,则范围反映当前插入点。 如果用户按下Delete键,则范围的长度为1,空字符串对象将替换该单个字符。
text : – 要插入的文本。
所以这就是方法和您的要求的解释如下所示:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { //Un-commend this check below :If you want to detect the word only while new line or white space charactor input //if ([text isEqualToString:@" "] || [text isEqualToString:@"\n"]) //{ // Getting the textView text upto the current editing location NSString * stringToRange = [textView.text substringWithRange:NSMakeRange(0,range.location)]; // Appending the currently typed charactor stringToRange = [stringToRange stringByAppendingString:text]; // Processing the last typed word NSArray *wordArray = [stringToRange componentsSeparatedByString:@" "]; NSString * wordTyped = [wordArray lastObject]; // wordTyped will give you the last typed object NSLog(@"\nWordTyped : %@",wordTyped); //} return YES; }
以下是使用UITextInput
和UITextInputTokenizer
来提供当前正在键入/编辑的单词的骨架结构示例。
- (void) textViewDidChange:(UITextView *)textView { NSRange selectedRange = textView.selectedRange; UITextPosition *beginning = textView.beginningOfDocument; UITextPosition *start = [textView positionFromPosition:beginning offset:selectedRange.location]; UITextPosition *end = [textView positionFromPosition:start offset:selectedRange.length]; UITextRange* textRange = [textView.tokenizer rangeEnclosingPosition:end withGranularity:UITextGranularityWord inDirection:UITextLayoutDirectionLeft]; NSLog(@"Word that is currently being edited is : %@", [textView textInRange:textRange]); }
这将为您提供当前正在输入的整个单词 。
例如,如果您输入输入并输入inp ,它将为您提供inp 。 此外,如果您位于单词middle的中间并将其更改为midddle ,它将为您提供中等 。 这里的技巧是标记化 。
我已将代码放在textViewDidChange:
这样您就可以在输入/编辑后获得该单词。 如果在最后一个字符更改之前需要它(即即将更改的单词),请将代码放在textView:shouldChangeTextInRange:replacementText:
.
PS:您必须处理边缘情况,例如句子和段落被粘贴/删除。 您可以通过更改粒度来修改此代码以获取字符/句子/段落等,而不仅仅是单词。 查看UITextGranularity
ENUM
的声明以获取更多选项:
typedef NS_ENUM(NSInteger, UITextGranularity) { UITextGranularityCharacter, UITextGranularityWord, UITextGranularitySentence, UITextGranularityParagraph, UITextGranularityLine, UITextGranularityDocument };
您可以简单地扩展UITextView
并使用以下方法返回光标当前位置周围的单词:
extension UITextView { func editedWord() -> String { let cursorPosition = selectedRange.location let separationCharacters = NSCharacterSet(charactersInString: " ") // Count how many actual characters there are before the cursor. // Emojis/special characters can each increase selectedRange.location // by 2 instead of 1 var unitCount = 0 var characters = 0 while unitCount < cursorPosition { let char = text.startIndex.advancedBy(characters) let int = text.rangeOfComposedCharacterSequenceAtIndex(char) unitCount = Int(String(int.endIndex))! characters += 1 } let beginRange = Range(start: text.startIndex.advancedBy(0), end: text.startIndex.advancedBy(characters)) let endRange = Range(start: text.startIndex.advancedBy(characters), end: text.startIndex.advancedBy(text.characters.count)) let beginPhrase = text.substringWithRange(beginRange) let endPhrase = text.substringWithRange(endRange) let beginWords = beginPhrase.componentsSeparatedByCharactersInSet(separationCharacters) let endWords = endPhrase.componentsSeparatedByCharactersInSet(separationCharacters) return beginWords.last! + endWords.first! } }
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { NSString *string = [textView.text stringByReplacingCharactersInRange:range withString:text]; if ([text isEqualToString:@"\n"] || [text isEqualToString:@" "]) { NSString *currentString = [string stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; NSLog(@"currentWord==> %@",currentString); } return YES; }
您的range
参数来自- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
delegate方法指向您更改UITextView
字符串值的确切位置。
结构的location
属性指向更改字符串索引,这很简单。 length
通常不等于text.length
,请注意,用户可以从字符串中选择字符以将其替换为另一个字符串。