Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 获取UITextView中当前键入的单词_Ios_Objective C_Uitextview_Substring_Nsrange - Fatal编程技术网

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!
    }
}