Ios 获取UITextView中当前键入的单词
我想在Ios 获取UITextView中当前键入的单词,ios,objective-c,uitextview,substring,nsrange,Ios,Objective C,Uitextview,Substring,Nsrange,我想在UITextView中获取当前键入的单词。在这里可以找到一种获取完全键入的单词的方法,但是,我希望在键入单词时获取该单词(无论它在哪里键入,UITextView的开头、中间、结尾) 我猜定义要键入的单词的是一个空格字符,后跟字母数字字符,或者如果当前位置(用range.location)是UITextView的开头,那么后面的任何内容都应该被视为单词。当另一个空白字符跟在后面时,一个单词就完成了键入 我试过: - (BOOL)textView:(UITextView *)textView
UITextView
中获取当前键入的单词。在这里可以找到一种获取完全键入的单词的方法,但是,我希望在键入单词时获取该单词(无论它在哪里键入,UITextView
的开头、中间、结尾)
我猜定义要键入的单词的是一个空格字符,后跟字母数字字符,或者如果当前位置(用range.location
)是UITextView
的开头,那么后面的任何内容都应该被视为单词。当另一个空白字符跟在后面时,一个单词就完成了键入
我试过:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text`
但是我找不到正确的范围
简而言之:我需要在UITextView
中找到子字符串,其中子字符串是当前键入的单词
编辑:因为问题出现了。我正在使用NSLayoutManager
并将NSTextContainer
绑定到它,然后将其作为layoutManager传递给NSTextStorage
EDIT2:(BOOL)textView:(UITextView*)textView的主要问题是范围。位置与指示器不同,但总是小于1。如果光标位于位置1,在键入一个字母后,range.location
将返回0。有办法吗?此外,UITextView
的text
属性似乎也关闭了1。当文本是foobar
并且我输出UITextView.text
时,我得到的是fooba
。因此range.location+1
返回异常range{0,1}超出范围;字符串长度0'
EDIT3:
使用NSTextStorage
而不是UITextView
?从-(BOOL)textView:(UITextView*)textView应该更改textinrange:(NSRange)range replacementText:(NSString*)获取所需结果可能更容易text
delegate方法指向更改UITextView
字符串值的确切位置
结构的location
属性指向不断变化的字符串索引,这很简单。length
通常不等于text.length
,请小心,用户可能会从字符串中选择字符以替换为另一个字符串 UITextView委托方法:-textView:textView应该更改textinrange:range replacement text:text
实际做的是询问是否应该在指定的textView.text
范围内的文本视图中替换指定的文本
每次在将字符更新到文本视图之前键入字符时,都会调用此方法。这就是为什么在文本视图
中键入第一个字符时,范围.位置
为0
仅当此方法的返回值为true时,textView
才会使用我们在textView
中键入的内容进行更新
这是apple提供的-textView:textView应更改textinrange:range replacementText:text
方法的参数定义:
范围:-当前选择范围。如果范围的长度为0,则范围反映当前插入点。如果用户按Delete键,则范围长度为1,空字符串对象将替换该单个字符。
文本:-要插入的文本
因此,对该方法的解释和您的需求可以满足如下要求:
- (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;
}
下面是一个骨架结构的示例,该骨架结构使用uitemideput
和uitemideputtokenizer
给出当前正在键入/编辑的单词
- (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]);
}
这将为您提供当前正在键入的整个单词
例如,如果您正在键入input并已键入inp,它将为您提供inp。进一步,如果你在单词<强>中< /强>中,并将其改为<强>中间强>,它将给你<强>中间< /强>。这里的技巧是标记化
我已将代码放在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!
}
}
扩展UITextView{
func editedWord()->字符串{
让cursorPosition=selectedRange.location
让separationCharacters=NSCharacterSet(charactersInString:)
//计算光标前的实际字符数。
//表情符号/特殊字符可以分别增加selectedRange.location
//以2代替1
var unitCount=0
变量字符=0
而单位计数<光标位置{
让char=text.startIndex.advancedBy(字符)
设int=text.rangeOfComposedCharacterSequenceAtIndex(字符)
unitCount=Int(字符串(Int.endIndex))!
字符+=1
}
让beginRange=Range(开始:text.startIndex.advancedBy(0),结束:text.startIndex.advancedBy(字符))
设endRange=Ra
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!
}
}