determine the maximum number of characters a UILabel can take
Asked Answered
H

2

4

Given a UILabel and a NSString, how do I determine how much of the string can fit inside the UILabel? I am using Xcode-5 and iOS-7.

I have been trying to see what I can extract from the thread Calculating UILabel Text Size but I am not getting anywhere with the responses there.

Hardshell answered 7/8, 2014 at 22:52 Comment(2)
How you go about this depends on what you want to do next. Do you want to resize the UILabel to accommodate all of the text? Do you want to truncate the text?Attempt
@jeffamaphone say the index is x, then I want to print range [0,x) in label1 and range [x,endOfString) in label2. Here label1 is the width I checked against.Hardshell
A
5

Well, what I did here works though there may be another, more efficient (yet less straight-forward) way.

What I did was just calculate the size of the rect needed for the text, see if it fits in the label's frame, and if not, chop off a character and try again.

@interface LTViewController ()

@property (nonatomic, weak) IBOutlet UILabel *label1;
@property (nonatomic, weak) IBOutlet UILabel *label2;

@end

@implementation LTViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    UILabel *label1 = self.label1;
    UILabel *label2 = self.label2;

    UIFont *font = label1.font;
    NSString *text = @"This is some text that will go into labels 1 and 2.";

    CGRect label1Frame = label1.frame;

    NSUInteger numberOfCharsInLabel1 = NSNotFound;

    for (int i = [text length]; i >= 0; i--) {
        NSString *substring = [text substringToIndex:i];
        NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:substring
                                                                             attributes:@{ NSFontAttributeName : font }];
        CGSize size = CGSizeMake(label1Frame.size.width, CGFLOAT_MAX);
        CGRect textFrame = [attributedText boundingRectWithSize:size
                                                        options:NSStringDrawingUsesLineFragmentOrigin
                                                        context:nil];

        if (CGRectGetHeight(textFrame) <= CGRectGetHeight(label1Frame)) {
            numberOfCharsInLabel1 = i;
            break;
        }
    }

    if (numberOfCharsInLabel1 == NSNotFound) {
        // TODO: Handle this case.
    }

    label1.text = [text substringToIndex:numberOfCharsInLabel1];
    label2.text = [text substringWithRange:NSMakeRange(numberOfCharsInLabel1, [text length] - numberOfCharsInLabel1)];
}

@end

This yields:

screen shot

It's up to you to handle the error conditions. For example, the rest doesn't completely fit into label2 and it's probably going to chop in the middle of a word more often then not.

Attempt answered 8/8, 2014 at 0:14 Comment(1)
thank you very much. +1 while I am still getting it to work with my app.Hardshell
C
0

Here is a swift solution for it:

func visibleSubString(label: UILabel) -> String? {

    let labelFrame = label.frame

    var numberOfCharsInLabel1 = 0

    guard let text = self.text, let fullAttributedText = self.attributedText else { return "" }
    var i = text.count

    while i >= 0 {
        let attributedText: NSAttributedString? = fullAttributedText.attributedSubstring(from: NSRange(location: 0, length: i))
        let size = CGSize(width: labelFrame.size.width , height: CGFloat.greatestFiniteMagnitude)
        if let textFrame = attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil) {
            if textFrame.height <= labelFrame.height {
                numberOfCharsInLabel1 = i
                break
            }
            i -= 1
        }
    }

    let visibleText = (text as NSString).substring(to: numberOfCharsInLabel1)
    return visibleText
}
Chrome answered 9/12, 2019 at 19:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.