Oct 08

Creating objects can be very expensive in terms of performance. This is especially true for UIControls that are also added to a UIView. Instead create a number of objects once and reuse them when needed.

Here’s a code snippet from a book reader application that lays out each text paragraph as it’s own UILabel. Since each page has a varying number of paragraphs each with varying number of lines of text I initially created the necessary UILabels each time a page was rendered. Bad idea!

Now I have an array (often called an object pool) of UILabels that have been created and added to the page UIView. Initially the hidden property is set to YES for all these labels. When a page is rendered a UILabel is picked from the pool, initialized with the appropriate text, location and size. And the hidden property is set to NO to display the label.

// Add new text to existing labels
for (int i = 0; i < MAX_LABELS; i++) {
   UILabel *textLabel = [textLabels objectAtIndex:i];
   if (i < [currentPage.paragraphs count]) {
      NSString *paragraph = [currentPage.paragraphs objectAtIndex:i];
      CGSize textSize = [paragraph sizeWithFont:textFont
 						constrainedToSize:CGSizeMake(PARAGRAPH_WIDTH, 1000)
 						lineBreakMode:UILineBreakModeWordWrap];
      textLabel.font = textFont;
      textLabel.frame = CGRectMake(PARAGRAPH_LEFT_MARGIN, yOffset, PARAGRAPH_WIDTH, textSize.height);
      textLabel.hidden = NO;
      textLabel.text = paragraph;
      yOffset = yOffset + textSize.height + PARAGRAPH_SPACING;
   } else {
      textLabel.hidden = YES;
      textLabel.text = @"";
   }
}

 
In addition to speed performance improvements this solution also has the significant benefit of managing memory much better. 

written by Nick \\ tags:

13 Responses to “Reuse Objects”

  1. Gonzojive Says:

    How much does this truly improve performance? Have you got some numbers? Memory management is quite tedious and I have found it only worthwhile to optimize in key places. For example, large images should quickly be deallocated when not in use. UITableViewCells should generally be reused, too, since so many are made. But in general I will and dealloc to my heart’s content.

  2. Nick Says:

    @Gonzojive: I don’t have any exact numbers from this app, but the improvement was visually very apparent. The numbers will also vary greatly with the type of object you’re reusing. In this case the objects were UILabels (UIViews), which are very expensive to create.

  3. ashish Says:

    Hello Nick,
    Thank you so much for sharing this code. I want to create an app some thing like that but I am stuck with how to calculate amount of text to be displayed in a view.
    I have an epub file.
    I am parsing the contents and storing each paragraph in an array. The problems which I am facing are:
    1. No of pages to calculate
    2. No of labels to be taken to display text.
    3. Spacing between the lines
    4. Bold and Italics to display in UILabels
    5. displaying images if any inside UIlabels.
    I am stuck with these things. I dont want to take webview I want to display content in labels only. Any help.
    Thank you
    ashish

  4. Nick Says:

    @ashish: If you are going to use this approach then you are limited to the capabilities of UILabel. For example, this excludes bold, italics and control over line spacing within each label. For your calculations I would use one UILabel per paragraph. Calculate the size required for the UILabel using one of the sizeWithFont methods of NSString(UIStringDrawing). For images you would have to layout UIImageViews in between UILabels.

  5. ashish Says:

    Hi Nick,

    thanks for your reply. But I am not sure in Stanza app they are also using UILabels with bold and italics. What approach they have followed?

    Thanks
    ashish

  6. Nick Says:

    @ashish: I don’t have any insight into the Stanza project so I don’t know any details about their implementation. I was part of the team that developed the Iceberg Reader, another popular ebook reader app, and it uses UIWebViews for the display.

    If you really don’t want to use a UIWebView, then you might want to checkout The Three20 Project which has some rich text UI components.

  7. ashish Says:

    Hi Nick

    Thanks a lot.
    The reviews about using The Three20 Project are very bad seems that apple rejects many app who are using it.

    Ok, If I would go for UIWebView then, is there any possibility to have a control over font size, font type and line spacing.
    How it would be possible to display XHTMl page by page. The user should feel that he is reading a book.If he wants to change font type and size, content should be formatted with in the frame.

    thank
    ashish

  8. Nick Says:

    @ashish: Anything you can do in HTML, you can do within a UIWebView. This includes font size, font type and line spacing. Just break up your book content into pages so you have one HTML page per book page.

  9. ashish Says:

    Hi Nick,

    I want to change font of UIWebView. I am doing like this
    int textFontSize; //any value
    NSString *jsString = [[NSString alloc] initWithFormat:@”document.getElementsByTagName(‘body’)[0].style.webkitTextSizeAdjust= ‘%d%%'”, textFontSize];

    [contentDisplay stringByEvaluatingJavaScriptFromString:jsString];

    The font is increasing, iphone orientation is in potrait, as font increases it goes out the boundries of screen. Is there any way so that increasing font should be visible in visible screen only. The webview should hyphenate the text.
    I have taken some screen shots also
    http://dl.dropbox.com/u/1658440/iphoneWebView/Archive1.zip

  10. Nick Says:

    @ashish: A web view does not hyphenate text, neither does a regular browser. I would suggest that you test the HTML in Mobile Safari. If the text goes outside the screen boundaries then you have an HTML problem. If it looks good in Safari, then you have a code problem.

  11. Mike Says:

    Hi Nick,

    I’m new to xcode and I’m trying to create an array of UILabels (verified complete per the debugger) and then programmatically, on demand alter attributes like .text (similar to your example above, I believe). The simple variable (yours: textLabel) gets updated appropriately (per the debugger), but the array element never gets updated. Any help, would be greatly appreciated.

    Thanks in advance,
    Mike

  12. Cyber Says:

    Hello, sir. I’m developing same epub reader app. And how do you solve the above problem? How can I solve hyphenate problem?

  13. Nick Says:

    @Cyber: If you want to do your own hyphenation, then you need to layout the text yourself. Word by word, line by line. As you get to the end of a line you need to create rules for hyphenation to determine where to insert the hyphen character, or to move the whole word to the next line. Not a trivial amount of work.

Leave a Reply