Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7564139
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 30, 20262026-05-30T13:50:28+00:00 2026-05-30T13:50:28+00:00

I am using Quartz for cell rendering in my table views. It works nice,

  • 0

I am using Quartz for cell rendering in my table views. It works nice, but to meet design concept I must somehow find the way to adjust line heights of the multiline text.
At the moment I am using convenient UIKit additions to NSString to render the text:

– drawInRect:withFont:lineBreakMode:alignment:

However, I can not find anywhere it the documentation the way to set up line spacing.
UIWebView is capable of that so it must use some lower level API to calculate line-height CSS property.
Can you recommend the solution compatible with iOS 3.0, 3.1?
I know I could try to use Core Text but it is available from the iOS 3.2.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-30T13:50:30+00:00Added an answer on May 30, 2026 at 1:50 pm

    I think the short answer here is no. I’ve worked with this problem for a while, and had to eventually implement my own solution for a label. I’ll post this solution below. Hopefully it’s helpful in implementing something yourself. Excuse the length and number of files, I broke it down for testability, and it handles ellipsizing as well.

    //MHLabel.h
    #import <UIKit/UIKit.h>
    #import "MHTextRuler.h"
    
    @interface MHLabel : UIView<MHTextRuler> {
    }
    
    @property (nonatomic, copy) NSString *text;
    @property (nonatomic, retain) UIFont *font;
    @property (nonatomic, retain) UIColor *textColor;
    @property (nonatomic) UITextAlignment textAlignment;
    @property (nonatomic) CGFloat lineSpacingMuliplier;
    @property (nonatomic) int maxLines;
    @property (nonatomic, readonly) int currentLines;
    @property (nonatomic, readonly) BOOL ellipsized;
    
    - (CGFloat) constrainHeightForCurrentWidth;
    
    @end
    
    
    //MHLabel.m
    #import "MHLabel.h"
    #import "UILabel+MH.h"
    #import "MHUI.h"
    #import "MHLabelLines.h"
    #import "MHLabelLayout.h"
    
    @interface MHLabel() 
    
    - (MHLabelLines *) linesForWidth: (CGFloat) width;
    
    @property (nonatomic, retain) NSMutableDictionary *lineCache;
    
    @end
    
    @implementation MHLabel
    
    @synthesize text = _text;
    @synthesize font = _font;
    @synthesize textColor = _textColor;
    @synthesize textAlignment = _textAlignment;
    @synthesize lineSpacingMuliplier = _lineSpacingMuliplier;
    @synthesize maxLines = _maxLines;
    @synthesize lineCache = _lineCache;
    
    - (id) initWithFrame: (CGRect) frame {
        if ((self = [super initWithFrame: frame])) {
            self.opaque = NO;
            self.maxLines = 0;
            self.lineSpacingMuliplier = 1;
            self.textAlignment = UITextAlignmentLeft;
            self.font = [MHUI fontOfSize: 16];
            self.textColor = [MHUI darkGrayText];
            self.lineCache = [NSMutableDictionary dictionary];
            self.contentMode = UIViewContentModeTopLeft;
        }
        return self;
    }
    
    - (void) dealloc {
        self.text = nil;
        self.font = nil;
        self.textColor = nil;
        self.lineCache = nil;
        [super dealloc];
    }
    
    - (void) setFrame: (CGRect) frame {
        [super setFrame: frame];
        [self setNeedsDisplay];
    }
    
    - (void) setText: (NSString *) text {
        if (![text isEqualToString: _text]) {
            [_text release];
            _text = [text copy];
            [self.lineCache removeAllObjects];
            [self setNeedsDisplay];
        }
    }
    
    - (void) setFont: (UIFont *) font {
        if (![font isEqual: _font]) {
            [_font release];
            _font = font;
            [_font retain];
            [self.lineCache removeAllObjects];
            [self setNeedsDisplay];
        }
    }
    
    - (void) setMaxLines: (NSInteger) maxLines {
        if (maxLines != _maxLines) {
            _maxLines = maxLines;
            [self.lineCache removeAllObjects];
            [self setNeedsDisplay];
        }
    }
    
    - (void) setTextColor: (UIColor *) textColor {
        if (![textColor isEqual: _textColor]) {
            [_textColor release];
            _textColor = textColor;
            [_textColor retain];
            [self setNeedsDisplay];
        }
    }
    
    - (void) setLineSpacingMuliplier: (CGFloat) lineSpacingMuliplier {
        if (lineSpacingMuliplier != _lineSpacingMuliplier) {
            _lineSpacingMuliplier = lineSpacingMuliplier;
            [self setNeedsDisplay];
        }
    }
    
    - (MHLabelLines *) linesForWidth: (CGFloat) width {
        NSString *key = [NSString stringWithFormat: @"w%d", (int) width];
        if (![self.lineCache objectForKey: key]) {
            MHLabelLines *labelLines = [MHLabelLayout linesForText: self.text constrainedToLines: self.maxLines andWidth: width withRuler: self];
            [self.lineCache setObject: labelLines forKey: key];
        }
        return [self.lineCache objectForKey: key];
    }
    
    - (CGFloat) constrainHeightForCurrentWidth {
        CGSize size = [self sizeThatFits: CGSizeMake(self.bounds.size.width, CGFLOAT_MAX)];
        CGRect newFrame = self.frame;
        newFrame.size = size;
        self.frame = newFrame;
        return size.height;
    }
    
    - (CGSize) sizeThatFits: (CGSize) size {
        CGFloat width = size.width;
        NSArray *lines = [self linesForWidth: width].lines;
        CGFloat textHeight = [@"X" sizeWithFont: self.font].height;
        CGFloat height = floorf(textHeight * self.lineSpacingMuliplier) * [lines count];
        return CGSizeMake(width, height);
    }
    
    - (void) drawRect: (CGRect) rect {
        CGFloat width = rect.size.width;
        NSArray *lines = [self linesForWidth: width].lines;
        CGFloat y = 0;
        CGFloat textHeight = [@"X" sizeWithFont: self.font].height;
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [self.textColor CGColor]);
        for (NSString *string in lines) {
            CGFloat x;
            if (self.textAlignment == UITextAlignmentLeft) {
                x = 0;
            } else {
                CGFloat textWidth = [string sizeWithFont: self.font].width;
                if (self.textAlignment == UITextAlignmentCenter) {
                    x = MAX(0, roundf((width - textWidth) / 2));
                } else {
                    x = MAX(0, width - textWidth);
                }
            }
            [string drawAtPoint: CGPointMake(x, y) forWidth: width withFont: self.font lineBreakMode: UILineBreakModeMiddleTruncation];
            y = floorf(y + (textHeight * self.lineSpacingMuliplier));
        }
    }
    
    - (int) currentLines {
        return [[self linesForWidth: self.bounds.size.width].lines count];
    }
    
    - (BOOL) ellipsized {
        return [self linesForWidth: self.bounds.size.width].ellipsized;
    }
    
    - (CGFloat) widthForText: (NSString *) text {
        return [text sizeWithFont: self.font].width;
    }
    
    @end
    
    //MHLabelLines.h
    #import <Foundation/Foundation.h>
    
    @interface MHLabelLines : NSObject {
    }
    
    @property (nonatomic, retain) NSArray *lines;
    @property (nonatomic) BOOL ellipsized;
    
    @end
    
    //MHLabelLines.m
    #import "MHLabelLines.h"
    
    @implementation MHLabelLines
    
    @synthesize lines = _lines;
    @synthesize ellipsized = _ellipsized;
    
    - (void) dealloc {
        self.lines = nil;
        [super dealloc];
    }
    
    @end
    
    //MHLabelLayout.h
    #import <Foundation/Foundation.h>
    #import "MHLabelLines.h"
    #import "MHTextRuler.h"
    
    @interface MHLabelLayout : NSObject {
    }
    
    + (MHLabelLines *) linesForText: (NSString *) text constrainedToLines: (int) maxLines andWidth: (CGFloat) width withRuler: (id<MHTextRuler>) ruler;
    
    @end
    
    //MHLabelLayout.m
    #import "MHLabelLayout.h"
    
    @interface MHLabelLayout()
    
    + (int) lastIndexForString: (NSString *) string thatFits: (CGFloat) width withRuler: (id<MHTextRuler>) ruler; 
    
    @end
    
    @implementation MHLabelLayout
    
    + (MHLabelLines *) linesForText: (NSString *) text constrainedToLines: (int) maxLines andWidth: (CGFloat) width withRuler: (id<MHTextRuler>) ruler {
        MHLabelLines *labelLines = [[[MHLabelLines alloc] init] autorelease];
        NSMutableArray *lines = [NSMutableArray array];
        NSString *remainingText = text;
        while ([remainingText length] > 0 && (maxLines == 0 || [lines count] < maxLines)) {
            int nextLineLastIndex = [self lastIndexForString: remainingText thatFits: width withRuler: ruler];
            NSString *nextString = [remainingText substringToIndex: nextLineLastIndex];
            remainingText = [remainingText substringFromIndex: MIN(nextLineLastIndex + 1, [remainingText length])];
            if ([lines count] + 1 == maxLines && [remainingText length]) {
                labelLines.ellipsized = YES;
                nextString = [nextString stringByAppendingString: @"..."];
                int ellipsizedIndex = [self lastIndexForString: nextString thatFits: width withRuler: ruler];
                while (ellipsizedIndex + 1 < [nextString length]) {
                    nextString = [[nextString substringToIndex: ellipsizedIndex] stringByAppendingString: @"..."];
                    ellipsizedIndex = [self lastIndexForString: nextString thatFits: width withRuler: ruler];
                }
            }
            [lines addObject: nextString];
        }
        labelLines.lines = lines;
        return labelLines;
    }
    
    + (int) lastIndexForString: (NSString *) string thatFits: (CGFloat) width withRuler: (id<MHTextRuler>) ruler {
        int index = 0;
        int nextIndex = 0;
        int stringLength = [string length];
        while (index < stringLength) {
            nextIndex = index + 1;
            NSRange searchRange = NSMakeRange(nextIndex, stringLength - nextIndex);
            NSRange foundRange = [string rangeOfString: @" " options: NSLiteralSearch range: searchRange];
            if (foundRange.location == NSNotFound) {
                nextIndex = stringLength;
            } else {
                nextIndex = foundRange.location;
            }
    
            CGFloat nextStringWidth = [ruler widthForText: [string substringToIndex: nextIndex]];
            if (nextStringWidth > width) {
                if (index == 0) {
                    index = nextIndex;
                }
                break;
            } else {
                index = nextIndex;
            }
        }
    
        NSRange newlineRange = [string rangeOfString: @"\n" options: NSLiteralSearch range: NSMakeRange(0, index)];
        if (newlineRange.location != NSNotFound) {
            index = newlineRange.location;
        }
        return index;
    }
    
    
    @end
    
    //MHTextRuler.h
    #import <Foundation/Foundation.h>
    
    @protocol MHTextRuler <NSObject>
    
    - (CGFloat) widthForText: (NSString *) text;
    
    @end
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have been trying to write an image on a layer using Quartz but
I've been trying to display text using a Quartz context, but no matter what
I'm using Quartz(1.6.6) , and it's a great system , but one things really
I want to draw some texts using Quartz. Now the app draws , but
I'm trying to build a simple scheduler using Quartz.NET, but when I try to
I am trying to implement full text search using Quartz 2D but it's a
Sorry for another non programming question, but I'm using Quartz.NET, a scheduler for .NET
I am using Quartz.NET for scheduling some custom tasks in our application. Everything works
I'm writing a scheduling application in Java using Quartz. I'm using the CronTrigger, but
I am using quartz.net to schedule regular events within asp.net mvc application. The scheduled

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.