簡體   English   中英

在UITextView中獲取當前鍵入的單詞

[英]Get currently typed word in a UITextView

我想在UITextView獲取當前鍵入的單詞。 獲取完全輸入單詞的方法可以在這里找到UITEXTVIEW:獲取最近uitextview中輸入的單詞,但是,我想在輸入單詞時輸入單詞(無論它在哪里輸入, UITextView開頭,中間,結尾)。

我想定義一個單詞的類型是一個空白字符后跟字母數字字符,或者如果當前位置(以某種方式用range.location )是UITextView的開頭,那么后續的任何內容都應該被視為單詞。 當另一個空格字符跟隨時,將完成一個單詞的輸入。

我嘗試過:

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text`

但我找到正確的范圍有問題。

簡而言之:我需要在UITextView找到子字符串,其中substring是當前鍵入的字。

編輯 :因為問題出現了。 我使用NSLayoutManager並綁定NSTextContainer它,然后作為的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.有什么辦法嗎? 此外, UITextViewtext屬性似乎也是1。 當文本是foobar並且我輸出UITextView.text然后我得到fooba而不是。 因此range.location+1返回異常Range {0, 1} out of bounds; string length 0' Range {0, 1} out of bounds; string length 0'

編輯3 :也許用NSTextStorage而不是UITextView更容易獲得我想要的結果?

以下是使用UITextInputUITextInputTokenizer來提供當前正在鍵入/編輯的單詞的骨架結構示例。

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

該UITextView的委托方法: -textView:textView shouldChangeTextInRange:range replacementText:text是什么actaully做的是,它會詢問是否指定的文本應在指定范圍內的文本視圖替換textView.text

每次我們在將其更新到文本視圖之前鍵入一個charactor時,都會調用此方法。 這就是為什么你所得到的range.location為0,當你鍵入的第一個字符textView

只有當此方法的返回為真時, 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;
}
- (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 ,請注意,用戶可以從字符串中選擇字符以將其替換為另一個字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM