Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting maximum number of lines entry on UITextView

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.

enter image description here

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?

like image 420
RGriffiths Avatar asked Oct 20 '13 14:10

RGriffiths


People also ask

How do I limit the number of characters in UITextField or UITextView?

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).

What is UITextField?

An object that displays an editable text area in your interface.


2 Answers

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!

like image 83
Stefan Arentz Avatar answered Sep 24 '22 03:09

Stefan Arentz


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);

}
like image 21
Sebastian Dwornik Avatar answered Sep 23 '22 03:09

Sebastian Dwornik