使UITextView的部分不可删除?

时间:2012-02-25 14:18:00

标签: objective-c ios cocoa-touch uitextview

我有一个UITextView,需要使特定部分不可删除。它是视图文本的前10个字符。

希望你能提供帮助,我只是想要这样,如果用户点击键盘上的删除键,它就会在达到第10个字符时停止。

希望你能提供帮助,谢谢。

编辑:

进展1感谢你们到目前为止的答案,让我进一步了解一下。

假设前缀为'123456789:'。我希望能够在这个前缀之后的任何地方输入,但它根本不可编辑,因此'123456789:'不应该被改变。 Fichek的答案完美地做到了这一点,但是前缀并不总是存在,所以如何检测它何时不在textview中?我认为if语句是这样做的,但似乎没有。

3 个答案:

答案 0 :(得分:14)

您可以使用委托方法textView:shouldChangeTextInRange:replacementText:告诉文本视图是否接受删除。

正如文件所说:

  

范围:当前选择范围。如果范围的长度为0,则范围反映当前插入点。 如果用户按下Delete键,则范围的长度为1,空字符串对象将替换该单个字符

修改

这是一种用户无法删除前十个字符的实现。但他可以在那里插入角色。

- (BOOL)textView:(UITextView *)textView shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (range.length==1 && string.length == 0) {
        // Deleting text
        if (range.location <= 9) {
            return NO;
        }
    }
    return YES;
}

这是一个他根本无法修改前十个字符的实现。

- (BOOL)textView:(UITextView *)textView shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (range.location <= 9) {
        return NO;
    }
    return YES;
}

答案 1 :(得分:8)

sch的最后编辑提供了一个不错的答案,但我希望提供一种稍微灵活的方法。

您必须记住复制/粘贴系统。用户可以选择文本字段中的所有文本并尝试粘贴可能完全可以接受的整个值,但if (range.location <= 9) { return NO; }将拒绝它。我这样做的方法是将一个字符串放在一起,这个字符串是成功编辑的结果,然后检查该字符串是否以您想要的前缀开头。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *resultString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSLog(@"resulting string would be: %@", resultString);
    NSString *prefixString = @"blabla";
    NSRange prefixStringRange = [resultString rangeOfString:prefixString];
    if (prefixStringRange.location == 0) {
        // prefix found at the beginning of result string
        return YES;
    }
    return NO;
}

修改:如果您想检查文本字段中的当前字符串是否以前缀开头,您可以使用rangeOfString:相同的方式:

NSRange prefixRange = [textField.text rangeOfString:prefixString];
if (prefixRange.location == 0) {
    // prefix found at the beginning of text field
}

答案 2 :(得分:1)

要获得完整的解决方案,您需要处理多种情况,包括可能在不可编辑的部分中开始并扩展到用户可以编辑的部分的剪切和粘贴操作。我添加了一个变量来控制包含不可编辑部分但扩展到可编辑部分的操作是否有效。如果有效,则调整范围以仅影响可编辑部分。

// if a nil is returned, the change is NOT allowed
- (NSString *)allowChangesToTextView:(UITextView *)textView inRange:(NSRange)changeRange withReplacementText:(NSString *)text
                       immutableUpTo:(NSInteger)lastReadOnlyChar adjustRangeForEdits:(BOOL)adjustRangeForEdits;
{
    NSString *resultString = @"";

    NSString *currentText = textView.text;
    NSInteger textLength = [currentText length];

    // if trying to edit the first part, possibly prevent it.
    if (changeRange.location <= lastReadOnlyChar)
    {
        // handle typing or backspace in protected range.
        if (changeRange.length <= 1)
        {
            return nil;
        }

        // handle all edits solely in protected range
        if ( (changeRange.location + changeRange.length) <= lastReadOnlyChar)
        {
            return nil;
        }

        // if the user wants to completely prevent edits that extend into the
        // read only substring, return no
        if (!adjustRangeForEdits)
        {
            return nil;
        }

        // the range includes read only part but extends into editable part.
        // adjust the range so that it does not include the read only portion.

        NSInteger prevLastChar = changeRange.location + changeRange.length - 1;
        NSRange newRange =  NSMakeRange(lastReadOnlyChar +  1, prevLastChar - (lastReadOnlyChar +  1) + 1);

        resultString = [textView.text stringByReplacingCharactersInRange:newRange withString:text];

        return resultString;
    }

    // the range does not include the immutable part.  Make the change and return the string
    resultString = [currentText stringByReplacingCharactersInRange:changeRange withString:text];
    return resultString;
}

这是从文本视图委托方法调用它的方式:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    // did the user press enter?
    if ([text isEqualToString:@"\n"])
    {
        [textView resignFirstResponder];
        return NO;
    }

    NSInteger endOfReadOnlyText = [self.spotTextLastSet length] - 1;
    NSString *newText = [self allowChangesToTextView:textView inRange:range withReplacementText:text
                                       immutableUpTo:endOfReadOnlyText adjustRangeForEdits:YES];

    if (newText == nil)
    {
        // do not allow!
        [TipScreen showTipTitle:@"Information" message:@"The first part of the text is not editable.  Please add your comments at the end."
                      ForScreen:@"editWarning"];
        return NO;
    }

    // lets handle the edits ourselves since we got the result string.
    textView.scrollEnabled = NO;
    textView.text = newText;


    // move the cursor to change range start + length of replacement text
    NSInteger newCursorPos = range.location + [text length];
    textView.selectedRange = NSMakeRange(newCursorPos, 0);
    textView.scrollEnabled = YES;

    return NO;
}