Hor*_*ray 3 objective-c uitextview ios
每当用户输入换行符时,我都会尝试在每行的开头添加一个数字.我希望数字按顺序排列(如在有序列表中),但是使用我当前的代码,如果用户最后没有添加新行,而是在中间添加行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;
}
Run Code Online (Sandbox Code Playgroud)
我刚发布的代码添加了一个编号列表,每个新行增加1.现在,如果您尝试在中间添加新行,而不是在最后,它将从最后一个行号增加1,它不会从前一行号增加.例如,如果用户添加6行UITextView,则用户转到第3行并添加新行,它将在第3行之后显示#7,因为每次用户创建新行时numbered都会增加1.
编辑

当用户在第1行之后添加新行时,我希望所有行都更新.希望这更清楚.
这个场景实际上比我预期的更复杂,因为在用户输入时动态创建编号列表,需要一个代码来处理与删除,插入,光标位置等相关的许多各种场景.但是我的答案的核心,这个代码基本上是通过将文本视图字符串分隔为"\n"分隔的"行"组件,从每行中删除当前尾随数字,按顺序重新添加适当的数字,然后重新组合字符串以返回到文本视图.
- (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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1564 次 |
| 最近记录: |