对于我正在编写的iOS应用程序,我使用的是UITextView,用户可以在其中插入有限的文本。
对于textview,有2个限制:
简而言之,最多是20行30个字符。
当用户在UITextView中键入一些文本并且当前句子是30个字符时,我希望它自动插入一个新行\n
(在该行的最后一个单词之前)并强制输入最后一个单词光标到下面的一行。
当一个用户有20行30个字符时(甚至更简单说:20行,最后一行有30个字符)我希望输入被阻止。
现在,大部分内容相当“简单”,但我所拥有的代码并未考虑边界情况,例如在前面的行中插入文本。
我查看了Apple的文档,但是我找不到在UITextView上实际强制进行这种自动换行的方法。
我的尝试是在shouldChangeTextInRange
委托方法中处理所有这些(使代码更加冗长,所以它更容易阅读)。
#define MAX_LENGTH_LINE 30
#define MAX_LENGTH_ROWS 20
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
// Check for backspaces, they should always be allowed?
if ([text length] == 0 && ![text isEqualToString:@"\n"])
return YES;
NSArray* lines = [textView.text componentsSeparatedByString:@"\n"];
// Check if there are a maximum of lines and the last line is already maxed out
NSString* lastLine = [lines objectAtIndex:[lines count] - 1];
if (([lines count] == MAX_LENGTH_ROWS) &&
(lastLine != nil) &&
([lastLine length] > MAX_LENGTH_LINE) &&
([text length] > 0))
return NO;
if ((lastLine != nil) &&
([lastLine length] > MAX_LENGTH_LINE))
{
NSRange range = [textView.text rangeOfString:@" " options:NSBackwardsSearch];
NSRange breakRange = [textView.text rangeOfString:@"\n" options:NSBackwardsSearch];
if (breakRange.location == NSNotFound)
breakRange = NSMakeRange(0, 1);
if (range.location == NSNotFound) {
range = NSMakeRange(0, 1);
}
if (range.location > breakRange.location)
{
textView.text = [textView.text stringByReplacingCharactersInRange:NSMakeRange(range.location, 1) withString:@"\n"];
}
else
{
textView.text = [textView.text stringByAppendingString:@"\n"];
}
}
if ([text isEqualToString:@"\n"])
{
if ([lines count] == MAX_LENGTH_ROWS)
return NO;
else {
return YES;
}
NSRange range = NSMakeRange(textView.text.length - 1, 1);
[textView scrollRangeToVisible:range];
}
return YES;
}
与此同时,我已经有一段时间了,我此刻失去了它。谁可以给出一些指针,只是将UITextView限制为我想要的20行/ 30个字符限制?
答案 0 :(得分:0)
这可能与您的总体目标背道而驰,但我脑海中最简单的答案是每次用户添加角色时重新分析字符串。然后添加角色无关紧要。而不是在shouldChangeTextInRange中完成所有这些:在textViewDidChange:中执行此操作。您将需要成为UITextViewDelegate,并且您需要一个单独的NSString类来保存上次成功的用户文本更新,以防您的用户尝试添加超出允许限制的字符。
这样的事情:
-(void)textViewDidChange:(UITextView *)textView
{
//Get the textview without any new line characters
NSMutableString *temporaryString = [NSMutableString stringWithString:[textView.text stringByReplacingOccurrencesOfString:@"\n" withString:@" "]];
bool updatePossible = true;
int i = 0, numberOfLinesSoFar = 0;
while(i + 30 < [temporaryString length])
{
//Go 30 characters in and start the reverse search for a word separation
i += 30;
int j = i;
//Get the location of the final word separation in the current line
while(j >= i && [temporaryString characterAtIndex:j] != ' ')
{
j--;
}
//This means we found a word separation
if(j > i)
{
i = j;
[temporaryString replaceCharactersInRange:NSMakeRange(i,1) withString:@"\n"];
}
//We didn't find a word separation
else
{
//Here we will just have to break the line at 30.
[temporaryString insertString:@"\n" atIndex:i];
}
numberOfLinesSoFar++;
//Check if we just wrote line 20 and still have characters to go.
if(numberOfLinesSoFar > 19 && i < [temporaryString length])
{
//Revert user change to the last successful character addition
textView.text = lastSuccessfulViewString;
updatePossible = false;
break;
}
}
if(updatePossible)
{
//If we are within the limits then update the global string (for undoing character additions) and the textview
textView.text = temporaryString;
lastSuccessfulViewString = temporaryString;
}
}
现在这不允许用户输入他们自己的新行字符,但是如果那么语句可以用一对来处理。
答案 1 :(得分:0)
经过一番摆弄后,创建了一个包含UITextView作为子视图的控件。
我让这个控件处理文本换行并将委托方法转发到注册为委托的视图。
它可能对其他人有帮助,所以我在这里发布了一个指向BitBucket的链接。
PS。它仍然非常冗长,但这是为了表明我是如何解决这个问题的。
https://bitbucket.org/depl0y/sbframework/src/master/SBFramework/Views/SBTextView?at=master