I would like to restrict the user of my iPad
app to entering a maximum of 20 lines when outputted on the pdf. The user enters text into the UITextView
(as shown below) and this is then later converted into a pdf document.
I realise that I will have to do a few of calculations depending on what text is entered as they type. Are there any methods that can help me out here? textFieldDidEndEditing
only allows me to check after it has been entered.
Also, as this would be far simpler, is there a way of limiting the number of lines a UITextField
can be?
If you have a UITextField or UITextView and want to stop users typing in more than a certain number of letters, you need to set yourself as the delegate for the control then implement either shouldChangeCharactersIn (for text fields) or shouldChangeTextIn (for text views).
An object that displays an editable text area in your interface.
You were close with the textFieldDidEndEditing
delegate method.
A better way though is to respond to the textView:shouldChangeTextInRange:replacementText:
delegate method and then see if the change that is about to happen would result in more lines that are allowed.
Here is an example on how to do that:
- (BOOL) textView:(UITextView *)textView
shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
static const NSUInteger MAX_NUMBER_OF_LINES_ALLOWED = 3;
NSMutableString *t = [NSMutableString stringWithString:
self.textView.text];
[t replaceCharactersInRange: range withString: text];
NSUInteger numberOfLines = 0;
for (NSUInteger i = 0; i < t.length; i++) {
if ([[NSCharacterSet newlineCharacterSet]
characterIsMember: [t characterAtIndex: i]]) {
numberOfLines++;
}
}
return (numberOfLines < MAX_NUMBER_OF_LINES_ALLOWED);
}
I put a complete example online at https://github.com/st3fan/StackOverflow/tree/master/TextViewWithLineLimit .. tested on iOS 7.0.2. Enjoy!
The following works with '\n' + wrapped line support.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.AutoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.AutocorrectionType = UITextAutocorrectionTypeNo;
self.KeyboardAppearance = UIKeyboardAppearanceAlert;
self.font = [UIFont fontWithName:@"Avenir" size:14];
self.maximumNumberOfLinesAllowed = 4;
self.delegate = self;
}
return self;
}
- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString*)aText
{
NSMutableString *t = [NSMutableString stringWithString: self.text];
[t replaceCharactersInRange: aRange withString: aText];
// First check for standard '\n' (newline) type characters.
NSUInteger numberOfLines = 0;
for (NSUInteger i = 0; i < t.length; i++) {
if ([[NSCharacterSet newlineCharacterSet] characterIsMember: [t characterAtIndex: i]]) {
numberOfLines++;
}
}
if (numberOfLines >= self.maximumNumberOfLinesAllowed)
return NO;
// Now check for word wrapping onto newline.
NSAttributedString *t2 = [[NSAttributedString alloc]
initWithString:[NSMutableString stringWithString:t] attributes:@{NSFontAttributeName:self.font}];
__block NSInteger lineCount = 0;
CGFloat maxWidth = self.frame.size.width;
NSLog(@"maxWidth = %.02f", maxWidth);
NSTextContainer *tc = [[NSTextContainer alloc] initWithSize:CGSizeMake(maxWidth, CGFLOAT_MAX)];
NSLayoutManager *lm = [[NSLayoutManager alloc] init];
NSTextStorage *ts = [[NSTextStorage alloc] initWithAttributedString:t2];
[ts addLayoutManager:lm];
[lm addTextContainer:tc];
[lm enumerateLineFragmentsForGlyphRange:NSMakeRange(0,lm.numberOfGlyphs)
usingBlock:^(CGRect rect,
CGRect usedRect,
NSTextContainer *textContainer,
NSRange glyphRange,
BOOL *stop)
{
lineCount++;
}];
// NSLog(@"%d", lineCount);
return (lineCount <= self.maximumNumberOfLinesAllowed);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With