UITextView限制最大輸入長度(UITextField相同)

這個命題,乍一想來似乎不難,只要判斷一下UITextView.text的長度不就限制住了嗎?

今天恰巧在開發中遇到這麼個需求,才真正發現有“插入”、“替換”、“粘貼”、“中文輸入”等各種細節問題。

在網上瀏覽了一圈,找到幾篇文章,也是各有缺陷。最終也沒有找到個合意的說法。


最後還是拿起官方文檔,不禁感嘆,原來偉大的Apple已經想好了,它給出的代理方法本身就是最佳解決方案。


以下就是我們用到的代理方法。(配上了鄙人的拙劣翻譯,英文好的同學們直接忽視吧)

****************************************************************************************************************************************************************************************

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
Asks the delegate whether the specified text should be replaced in the text view.
詢問代理Text View中的指定文本是否可以被替換。
Parameters
textView

The text view containing the changes.

包含變化的Text View。

range

The current selection range. If the length of the range is 0, range reflects the current insertion point. If the user presses the Delete key, the length of the range is 1 and an empty string object replaces that single character.

當前選中的範圍。如果範圍的長度是0,range反映的是當前插入點。如果用戶按下刪除鍵,範圍的長度就是1,並使用一個空字符串對象替換該字符。

text

The text to insert.

將被插入的文本。

Return Value

YES if the old text should be replaced by the new text; NO if the replacement operation should be aborted.

如果舊文本可以被新文本替換,返回YES;如果要中止這個替換操作,返回NO。

Discussion

The text view calls this method whenever the user types a new character or deletes an existing character. Implementation of this method is optional. You can use this method to replace text before it is committed to the text view storage. For example, a spell checker might use this method to replace a misspelled word with the correct spelling.

無論用戶什麼時候輸入新字符或者刪除已存在的字符,Text View都會調用這個方法。可以選擇是否實現這個方法。你可以在文本被提交到Text View裏面之前把它替換掉。例如,拼寫檢查器可以使用這個方法把寫錯的單詞替換成正確的。

***********************************************************************************************************************************************************************************


從官方文檔描述可以看出,其實Apple把“插入”和“刪除”都解釋成了“替換”。插入就是用文本替換空字符串,刪除就是用空字符串替換文本。

按照這個思路,即 將要生成的文本長度 = 原始文本長度 - 選中文本長度 + 輸入文本長度。再考慮到刪除的情況,我的代碼如下:

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

{

    if ([text isEqualToString:@""] && range.length > 0) {

        //刪除字符肯定是安全的

        return YES;

    }

    else {

        if (textView.text.length - range.length + text.length > MAX_INPUT_LENGTH) {

            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"超出最大可輸入長度" message:nil delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil];

            [alert show];

            return NO;

        }

        else {

            return YES;

        }

    }

}


最後,再說一下中文輸入的情況。

當使用中文輸入法時,也是每按下一個字母就會調用一次該方法。通過打印textView.text的變化發現:

1.中文輸入實際上是先將字母寫入到textView中,字與字之間用空格分隔。如輸入“zhongguo”時,textView.text實際上是"zhong guo";輸入“zhguo”,textView.text也會存成"zh guo";輸入“zg”,就是"z g"。

2.然後用戶選擇需要的漢字,才用相應漢字替換保存在textView.text中的拼音字母。如果用戶未選擇漢字或空格(認爲選擇第一個漢字),而按下“確認”按鈕,就直接將保存的拼音字母寫入textView.text。

這裏有一個問題就是,用戶選擇漢字時,剛剛的代理方法並不會被調用,這裏就會有一個誤差。"zhong guo"的length是9,而選擇漢字之後length就變成了2。需要使用textViewDidChange代理方法,捕獲到用戶的操作,才能實時的跟蹤到textView裏面文本長度的變化。

注意:美中不足是,當使用聯想時,用戶輸入的字母個數可能會比實際能進入到textView中的字符數更少,textViewDidChange代理方法也不能中止用戶選擇聯想詞的行爲(不會調用shouldChangeTextInRange代理方法)。所以如果對最大輸入長度要求非常嚴格的應用,應該留下一定餘量,避免溢出。




***************************************************************************************************************************************************************************************
發佈了10 篇原創文章 · 獲贊 0 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章