每个新行添加一个编号列表UITextView

我试图添加一个数字到每行的开始,每当用户input一个换行符。 我想要数字顺序(如在一个有序的列表),但与我目前的代码,如果用户不添加一个新的行在最后,而是添加在UITextView中间的行,它会从底部的位置继续计数 – 这意味着NSUInteger我做了增量,并没有考虑到用户在最后没有做出新的路线。

 - (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,而不会从前一个线号增加。 例如,如果用户将6行添加到UITextView ,则用户进入第3行并添加一个新行,它将在行#3之后显示#7,因为每当用户增加一个新行1。

编辑

在这里输入图像说明

当用户在第1行之后添加一个新行时,我想要更新所有行。 希望这个更清楚。

这个场景实际上比我预期的要复杂得多,因为在用户input时dynamic地创build一个编号列表,需要一个处理许多与删除,插入,光标位置等有关的各种场景的代码。但是我的答案的核心是代码的基本工作原理是将文本视图string分隔成由“\ n”分隔的“行”组件,从每行删除当前的尾随数字,按顺序重新添加适当的数字,然后重新组合string以返回到文本视图。

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