每行添加一个编号列表UITextView [英] Every new line add a numbered list UITextView

查看:145
本文介绍了每行添加一个编号列表UITextView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每当用户输入换行符时,我都试图在每行的开头添加一个数字.我希望数字按顺序排列(例如在有序列表中),但是使用我当前的代码,如果用户没有在末尾添加新行而是在UITextView的中间添加了该行,它会从它从底部开始的位置继续计数-表示NSUInteger我进行了递增操作,并且没有考虑到用户没有在末尾添加新行.

I'm trying to add a number to the beginning of each row whenever the user enters a newline. I'd like the numbers to go in order (like in an ordered list), but with my current code, if the user does not add a new line at the end but instead adds the line in the middle of the UITextView, it will continue counting from where it left off at the bottom -- meaning that the NSUInteger I made increments and doesn't take into account that the user did not make the new line at the end.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if ([text isEqualToString:@"\n"])
    {
        numbered ++;
        NSString *string = [NSString stringWithFormat:@"\n%lu ", (unsigned long)numbered];
        [self insertXEveryNewLine:range :textView :string];
        
        return NO;
    }
    return YES;
}


- (BOOL)insertXEveryNewLine:(NSRange)place :(UITextView *)View :(NSString *)something
{
    NSRange cursor = NSMakeRange(place.location + 3, 0);
    
    NSMutableString *mutableT = [NSMutableString stringWithString:View.text];
    [mutableT insertString:something atIndex:place.location];
    [View setText:mutableT];
    return NO;
}

我刚刚发布的代码添加了一个编号列表,每增加一行,编号列表就会增加1.现在,如果您尝试在中间而不是末尾添加新行,则它将从最后一个行号开始增加1,而不会从上一个行号开始增加.例如,如果用户向UITextView添加6行,则用户转到第3行并添加新行,它将在第3行之后显示#7,因为每次用户创建新行增加1.

The code I just posted adds a numbered list which increases by 1 every new line. Now, if you try adding a new line in the middle, not at the end, it will increase by 1 from the last line number, it won't increase from the previous line number. For example, if the user adds 6 lines to the UITextView, then the user goes to line #3 and adds a new line, it will display #7 after line #3, because every time the user makes a new line numbered gets increased by 1.

修改

当用户在第1行之后添加新行时,我希望所有行都进行更新.希望这更清楚.

When the user adds a new line after line 1, I want all lines to update. Hope this is clearer.

推荐答案

此方案实际上比我预期的在逻辑上更加复杂,因为在用户输入时动态创建编号列表需要代码来处理与删除有关的许多方案,插入,光标位置等.但是,从我的回答的核心出发,这段代码基本上是通过将文本视图字符串分成以"\ n"分隔的行"组件,从每行中删除当前尾随数字,重新添加来工作的适当的数字顺序排列,然后重新组合字符串以返回到文本视图.

This scenario is actually more logistically complicated than I'd anticipated because dynamically creating a numbered list upon user entry, requires a code that handles many various scenarios relating to deletion, insertions, cursor position, etc. But at the heart of my answer, this code basically works by separating the text view string into "line" components separated by "\n", removes the current trailing numbers from each line, re-adds the appropriate numbers in order, then recombines the string to go back into the text view.

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

    // Add "1" when the user starts typing into the text field
    if (range.location == 0 && textView.text.length == 0) {

        // If the user simply presses enter, ignore the newline
        // entry, but add "1" to the start of the line.
        if ([text isEqualToString:@"\n"]) {
            [textView setText:@"1 "];
            NSRange cursor = NSMakeRange(range.location + 3, 0);
            textView.selectedRange = cursor;
            return NO;
        }

        // In all other scenarios, append the replacement text.
        else {
            [textView setText:[NSString stringWithFormat:@"1 %@", text]];
        }
    }

    // goBackOneLine is a Boolean to indicate whether the cursor
    // should go back 1 line; set to YES in the case that the
    // user has deleted the number at the start of the line
    bool goBackOneLine = NO;

    // Get a string representation of the current line number
    // in order to calculate cursor placement based on the
    // character count of the number
    NSString *stringPrecedingReplacement = [textView.text substringToIndex:range.location];
    NSString *currentLine = [NSString stringWithFormat:@"%lu", [stringPrecedingReplacement componentsSeparatedByString:@"\n"].count + 1];

    // If the replacement string either contains a new line
    // character or is a backspace, proceed with the following
    // block...
    if ([text rangeOfString:@"\n"].location != NSNotFound || range.length == 1) {

        // Combine the new text with the old
        NSString *combinedText = [textView.text stringByReplacingCharactersInRange:range withString:text];

        // Seperate the combinedText into lines
        NSMutableArray *lines = [[combinedText componentsSeparatedByString:@"\n"] mutableCopy];

        // To handle the backspace condition
        if (range.length == 1) {

            // If the user deletes the number at the beginning of the line,
            // also delete the newline character proceeding it
            // Check to see if the user's deleting a number and
            // if so, keep moving backwards digit by digit to see if the
            // string's preceeded by a newline too.
            if ([textView.text characterAtIndex:range.location] >= '0' && [textView.text characterAtIndex:range.location] <= '9') {

                NSUInteger index = 1;
                char c = [textView.text characterAtIndex:range.location];
                while (c >= '0' && c <= '9') {

                    c = [textView.text characterAtIndex:range.location - index];

                    // If a newline is found directly preceding
                    // the number, delete the number and move back
                    // to the preceding line.
                    if (c == '\n') {
                        combinedText = [textView.text stringByReplacingCharactersInRange:NSMakeRange(range.location - index, range.length + index) withString:text];

                        lines = [[combinedText componentsSeparatedByString:@"\n"] mutableCopy];

                        // Set this variable so the cursor knows to back
                        // up one line
                        goBackOneLine = YES;

                        break;
                    }
                    index ++;
                }
            }

            // If the user attempts to delete the number 1
            // on the first line...
            if (range.location == 1) {

                NSString *firstRow = [lines objectAtIndex:0];

                // If there's text left in the current row, don't
                // remove the number 1
                if (firstRow.length > 3) {
                    return  NO;
                }

                // Else if there's no text left in text view other than
                // the 1, don't let the user delete it
                else if (lines.count == 1) {
                    return NO;
                }

                // Else if there's no text in the first row, but there's text
                // in the next, move the next row up
                else if (lines.count > 1) {
                    [lines removeObjectAtIndex:0];
                }
            }
        }

        // Using a loop, remove the numbers at the start of the lines
        // and store the new strings in the linesWithoutLeadingNumbers array
        NSMutableArray *linesWithoutLeadingNumbers = [[NSMutableArray alloc] init];

        // Go through each line
        for (NSString *string in lines) {

            // Use the following string to make updates
            NSString *stringWithoutLeadingNumbers = [string copy];

            // Go through each character
            for (int i = 0; i < (int)string.length ; i++) {

                char c = [string characterAtIndex:i];

                // If the character's a number, remove it
                if (c >= '0' && c <= '9') {
                    stringWithoutLeadingNumbers = [stringWithoutLeadingNumbers stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""];
                } else {
                    // And break from the for loop since the number
                    // and subsequent space have been removed
                    break;
                }
            }

            // Remove the white space before and after the string to
            // clean it up a bit
            stringWithoutLeadingNumbers = [stringWithoutLeadingNumbers stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

            [linesWithoutLeadingNumbers addObject:stringWithoutLeadingNumbers];
        }

        // Using a loop, add the numbers to the start of the lines
        NSMutableArray *linesWithUpdatedNumbers = [[NSMutableArray alloc] init];

        for (int i = 0 ; i < linesWithoutLeadingNumbers.count ; i ++) {
            NSString *updatedString = [linesWithoutLeadingNumbers objectAtIndex:i];
            NSString *lineNumberString = [NSString stringWithFormat:@"%d ", i + 1];
            updatedString = [lineNumberString stringByAppendingString:updatedString];
            [linesWithUpdatedNumbers addObject:updatedString];
        }

        // Then combine the array back into a string by re-adding the
        // new lines
        NSString *combinedString = @"";

        for (int i = 0 ; i < linesWithUpdatedNumbers.count ; i ++) {
            combinedString = [combinedString stringByAppendingString:[linesWithUpdatedNumbers objectAtIndex:i]];
            if (i < linesWithUpdatedNumbers.count - 1) {
                combinedString = [combinedString stringByAppendingString:@"\n"];
            }
        }

        // Set the cursor appropriately.
        NSRange cursor;
        if ([text isEqualToString:@"\n"]) {
           cursor = NSMakeRange(range.location + currentLine.length + 2, 0);
        } else if (goBackOneLine) {
            cursor = NSMakeRange(range.location - 1, 0);
        } else {
            cursor = NSMakeRange(range.location, 0);
        }

        textView.selectedRange = cursor;

        // And update the text view
        [textView setText:combinedString];

        return NO;
    }

    return YES;
}

这篇关于每行添加一个编号列表UITextView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆