My problem is this: I have dynamic content in an iOS app (such as twits - although this is not a twitter app) that include both text and images (mostly icons/emoticons and thumbnails). I want to render both text and images together in a table row. The main difficulty here is that each row will have a different size (making caching harder), and I need to calculate image size dynamically to fit text around on each image occurrence (I can have like 20 emoticons one next to another + text + more emoticons + etc.).
I've been looking around and I've tried a few approaches. My initial idea was to use UIWebView. I was able to create a sample app with one UIWebView per row, and even with some "smart" NSCache for pre-rendered cells performance was not very good, plus I had to deal with UIWebView javascript callbacks to figure out when content was properly loaded.
My second attempt is to overwrite drawRect for a new UITableViewCell. Inside the drawRect method I'm using NSAttributedString and the NSSelectorFromString to set the ranges for each kind of content (regular text, bold, italic, different color, images). To fit the images I'm using the CTRunDelegateCallbacks callbacks (getAscent, getDescent, getWidth). Something like this:
CTRunDelegateCallbacks callbacks;
callbacks.version = kCTRunDelegateVersion1;
callbacks.getAscent = ascentCallback;
callbacks.getDescent = descentCallback;
callbacks.getWidth = widthCallback;
CTRunDelegateRef delegate = CTRunDelegateCreate(&callbacks, (__bridge void *)imgAttr); // img Attr is a Dictionary with all image info
For more details on this approach please check this excellent post: http://www.raywenderlich.com/4147/how-to-create-a-simple-magazine-app-with-core-text#
Finally, two questions:
Is this the best approach, can I make this with good performance? I'm wondering if having to call drawRect for each cell for every scroll wont be cumbersome - is there anything I could do in advance? I've been playing around for a while, and it's still a big lagged - but I haven't yet tried to cache every single row in a separate thread and use that in cellForRowAtIndexPath (although that may exceed memory use);
I can't figure out the best way to obtain the row height for each tableview cell. How can I know the height used by my drawRect function after NSAttributedString has properly processed all my content?
--- Adding more info
After my drawRect creates all content (strings and images) I'm trying to use boundingRectWithSize to get the proper height:
CGRect frame = [self.attString boundingRectWithSize:CGSizeMake(320, 10000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading | NSStringDrawingUsesDeviceMetrics context:nil];
This works fine if it's text only, but when I add the image glyphs to the content it does not calculate the height properly...