2014-12-15 2 views
3

Я пытаюсь добавить число в начало каждой строки всякий раз, когда пользователь вводит новую строку. Я бы хотел, чтобы числа были в порядке (например, в упорядоченном списке), но с моим текущим кодом, если пользователь не добавляет новую строку в конец, а вместо этого добавляет строку в середине UITextView, она будет продолжайте отсчет с того места, где он остановился внизу - это означает, что NSUInteger я сделал приращения и не учитываю, что пользователь не сделал новую строку в конце.Каждая новая строка добавляет нумерованный список UITextView

- (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 и добавляет новую строку, он отображает # 7 после строки # 3, поскольку каждый раз, когда пользователь делает новую строку numbered, увеличивается на 1.

Редактировать

enter image description here

Когда пользователь добавляет новую строку после строки 1, я хочу все строки для обновления. Надеюсь, это яснее.

+1

Непонятно, о чем вы просите о помощи. – shim

+1

У вашего кода есть и другие проблемы. Он не обрабатывает вставку пользователя в текст, особенно если некоторый текст был выделен во время вставки. – rmaddy

+1

Если пользователь добавляет 6 строк в UITextView, пользователь переходит к строке # 3 и добавляет новую строку, он отображает 7 после строки # 3, потому что каждый раз, когда пользователь делает новую строку с номером, увеличивается на 1 – Horray

ответ

5

Этот сценарий на самом деле более логически сложный, чем я ожидал, поскольку для динамического создания нумерованного списка при вводе пользователя требуется код, который обрабатывает множество различных сценариев, связанных с удалением, вставками, позицией курсора и т. Д. Но в основе мой ответ, этот код в основном работает, разделяя строку текстового представления на «линейные» компоненты, разделенные «\ 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; 
} 
+0

Я забыл добавить «удалить» обновление ... Добавлюсь позже ... –

+0

Большое вам спасибо. Вы ответили на вопрос очень подробно! – Horray

+0

Нет проблем :), но я также немного поправлю свой ответ чуть позже, чтобы обработать промежутки после того, как я получу шанс ... –