#iphone #objective-c #cocoa-touch #uitextview
#iPhone #objective-c #cocoa-touch #uitextview
Вопрос:
Я думаю, это немного неудобный вопрос, поэтому позвольте мне перефразировать его с иллюстрацией:
У меня есть UITextView, который ограничен определенным количеством символов. Это регулярно проверяется с помощью - (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString *)aText
. Как только размер текста превышает пороговое значение удержания (на иллюстрации это было бы 8 символов), приложение переходит к следующему TextView и копирует следующий введенный символ (в данном случае p) в новый UITextView. Затем пользователь может ввести оставшуюся часть слова (в данном случае py).
Вместо разделения слова на два UITextViews, я хотел бы, чтобы в следующем UITextView было все слово ‘happy’. Другими словами, мне нужно скопировать ‘hap’ из строки 1 в начало строки 2, а затем удалить ‘hap’ из строки 1.
Я придумал этот код, который проверяет строку 1 на наличие пробелов и копирует все после пробела в строку 2. Но это не сработает:
NSLog(@"text of current string: %@", aTextView.text); // e.g. "I am hap"
NSLog(@"chars in aTextView.text: %i", aTextView.text.length); // e.g. 8 chars
NSLog(@"text for next string: %@ ", aText); // e.g. "py"
NSString *aTextModified = aText;
for (int i = aTextView.text.length; i > 0; i--) {
NSLog(@"I currently check: '@%'", [aTextView.text characterAtIndex:i]);
if ([[aTextView.text characterAtIndex:i] isEqualToString:@" "]) {
// job done
} else {
NSLog(@"I add %@ infront of %@", [aTextView.text characterAtIndex:i], aText);
aTextModified = [NSString stringWithFormat:@"%@%@", [aTextView.text characterAtIndex:i], aText];
NSLog(@"I delete %@ as I have put it into the next string...", [aTextView.text characterAtIndex:i]);
[aTextView.text characterAtIndex:i] = @"";
}
}
XCode выдает мне предупреждение «Недопустимый тип получателя «unichar» для строки if ([[aTextView.text characterAtIndex:i] isEqualToString:@" "])
. Полагаю, я неправильно использую characterAtIndex? Мне не разрешено применять это к тексту (который должен быть UIString) в UITextView?
Кроме того, я получаю сообщение об ошибке «Значение LValue требуется как левый вариант присвоения» для последней строки [aTextView.text characterAtIndex:i] = @"";
Опять же, я думаю, я действительно не понимаю, как получить доступ к символу в UITextView и изменить его.
Я был бы очень благодарен за любые предложения о том, как сделать это правильно, и если есть более простые способы достичь того, что я пытаюсь сделать.
Комментарии:
1. что произойдет, если размер слова превышает пороговое значение?
2. @Nick Weaver: Ну, оно не может быть больше порогового значения, так как оно будет автоматически обрезано. Например. если вы попытаетесь ввести ‘areallylongword’, оно будет обрезано после ‘areallylo’, а ‘n’ будет помещено в следующую строку. Я проверяю строку после каждого введенного символа. Кроме того, мои строки 1 и 2 намного больше, чем 8 символов — я просто взял это для иллюстрации, чтобы упростить задачу. На самом деле, я смотрю на весь UITextView, заполняющий экран… Проблема заключается в проверке последнего слова, введенного на этом экране, и необходимости его переноса на следующий экран. Большое спасибо за вашу помощь
Ответ №1:
Несколько вещей
NSLog(@"I currently check: '@%'", [aTextView.text characterAtIndex:i]);
Здесь вы получаете C
символ, поэтому вы должны использовать %c
вместо него.
[[aTextView.text characterAtIndex:i] isEqualToString:@" "]
Опять же, то, что вы здесь делаете, — это отправка сообщения C
символу, который неверен. Вы можете изменить его на [aTextView.text characterAtIndex:i] == " "
, чтобы сделать это правильно.
[aTextView.text characterAtIndex:i] = @"";
text
определяется как неизменяемая строка. Вы не можете изменить это таким образом. Вам придется объявить изменяемую строку и скопировать содержимое text
поверх. После внесения изменений в изменяемую строку вы можете установить для нее значение text
.
Это также даст вам последнее слово.
NSScanner *wordsScanner = [NSScanner scannerWithString:@"I am happy however I want the last word and it's positions !!!!"];
NSString *theLastWord;
while (![wordsScanner isAtEnd]) {
[wordsScanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] intoString:amp;theLastWord];
}
// theLastWord has the value.
Редактировать
NSString *text = aTextView.text;
int index = text.length - 1;
while ([text characterAtIndex:index] != " ") {
index--;
}
NSString stringToBeMoved = [text substringFromIndex:index];
aTextView.text = [text substringToIndex:(index 1)];
Комментарии:
1. Большое спасибо. Я попробую и дам вам знать, как все прошло.
2. На самом деле, я немного смущен объявлением изменяемой строки и последующим копированием содержимого текста… как мне это сделать? Просто
Char replacementChar = "";
а затем[aTextView.text characterAtIndex:i] = replacementChar;
не сработало бы, верно?
Ответ №2:
Хорошо, давайте начнем с простого. Я создал следующее регулярное выражение, которое будет соответствовать последнему слову в строке, и если есть символы, не являющиеся словами, такие как пробелы или знаки препинания.
Я думаю, что проще работать с регулярным выражением и определять, где оно соответствует, чтобы манипулировать строкой. Однако я не уверен, какой будет производительность в больших текстах, но я думаю, что это можно решить, используя некоторые предположения, такие как: textview one не будет пропускать первые 1000 символов, поэтому может быть безопасно использовать только последние 50 символов для регулярного выражения.
NSString *aString = @"I am happy however I want the last word and it's positions !!!!";
NSString * const regularExpression = @"\b(\w )\b(\W*)$";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regularExpression
options:NSRegularExpressionCaseInsensitive | NSRegularExpressionUseUnicodeWordBoundaries
error:amp;error];
NSArray *matches = [regex matchesInString:aString
options:0
range:NSMakeRange(0, [aString length])];
for (NSTextCheckingResult *match in matches) {
for (int i = 0; i < [match numberOfRanges]; i ) {
NSLog(@"substring %d: %@", i, [aString substringWithRange:[match rangeAtIndex:i]]);
}
}
Если оно совпадает, вы можете легко выполнить итерацию по результату, который дает вам последнее слово и некоторые завершающие символы, не являющиеся словами, но самое главное, что вы получаете диапазон каждого соответствия, чтобы вы могли определить, превышен ли порог.
Комментарии:
1. Спасибо, Ник. Но я думаю, проблема в том, что я не получаю полную строку. Я получаю только символ за раз! Помните, что я использую
- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString *)aText
— поэтому я получаю только текст, который обычно состоит только из одного символа. Другими словами, приложение постоянно проверяет, когда вы вводите каждый символ. Если вы попытаетесь добавить еще один символ и пересечь пороговое значение, я хочу отделить начало последнего слова, которое я пытался ввести (например, позиции, которые я больше не мог вводить). Я хочу, чтобы ‘positi’ копировался в следующий UITextView.2. Я попытаюсь поработать в вашем коде и дам вам знать, где я застрял. Я думаю, моя самая большая проблема в том, что я не использую NSMakeRange…
3. @n.evermind ну, вы могли бы переключиться на метод делегирования
textViewDidChange
и просто использовать myTextField.text в качестве входных данных, чтобы проверка происходила каждый раз, когда пользователь нажимает клавишу.