Core Text Objective-C Wrapper

One of the most promising and mysterious new frameworks introduced in iOS 3.2 is Core Text. Apple defines Core Text as a “text drawing engine”, which allows Mac (and now iPad) apps to render rich text on any graphics context. Strings drawn with Core Text feature lots of custom settings such as detailed font information, columns, variable line and paragraph heights and several different attributes, which designers and font aficionados surely understand much better than I do. Many new apps have been using this framework since the release of the iPad, particularly newspapers and ebook reader applications, rendering gorgeous text in custom fonts, many of them not available natively in iOS. This framework is also used in lifestyle and corporate applications, too, where using a custom font is sometimes required to match the specifications of brands and trademarks. coretextwrapper.pngIt is very important to understand that Core Text is really just a text drawing engine to be used on top of Quartz (Core Graphics), to render rich text on any graphics context. Core Text cannot be used to create a rich text editor, for example, so don’t expect to extend UITextView with it. But you can use it to draw any kind of rich text on screen, which can make you avoid using UIWebView instances for that.

One of the most interesting capabilities of Core Text is being able to render text in several columns. However, Core Test is a C-based framework, and I think that understanding and using the concepts and structures required to render text in columns can be particularly tricky. To make the my life and that of my fellow developers easier, I’ve created a small set of Objective-C classes that encapsulate the creation of framesetters, attributed strings and other constructions, and takes care of the creation of several columns, as well as the division of the text in several pages if required.

The API interface is very simple (in purpose) and I’m pretty sure you’ll be able to integrate it very easily in your own projects, particularly if you look at the sample project where the classes are used. I’ve also added a category for UIFont, that returns the associated CTFontRef pointer, in a similar fashion to UIImage, which is able to return a pointer to the underlying CGImageRef pointer. It also allows to create a CTFontRef from any font embedded in the application bundle. I am puzzled that the framework designers haven’t included this by default in UIKit.

A future extension I’d like to add would be a couple of categories to parse simple RTF or HTML strings (to start with, probably just with bold and italic text) and create the appropriate attributed string from it; there’s a couple of AppKit extensions to NSAttributedString that do exactly that, but for the moment they are only available in the Mac version of Cocoa, and I haven’t found anything similar for iOS yet (feel free to leave a comment below if you know about some implementation for generating NSAttributedStrings from HTML or RTF text!)

The code, as usual, is available through Github (BSD license), so feel free to use it and even contribute bug fixes or enhancements if you want. The font embedded in the project is Polsku Regula, available through the Open Font Library.org. The project requires Xcode 3.2.3 and the iOS SDK 4.0, and it creates a simple application that works on the iPad (iOS 3.2). As usual, use it at your own risk. Enjoy!

Similar Posts:

Comments

30 Comments so far. Leave a comment below.
  1. Andre,

    Hi,

    Thanks for the nice wrapper. I was wondering how I can turn on text justification for the columns.

    Ta,

    Andre

  2. I spent a lot of time to figure out why following code cause my application hang, CTFontRef customFont = CTFontCreateWithName(CFSTR(“myfont”), 12,NULL); //myfont is the custom font.

    seems customFont is only work for UIFont, so to create a CTFontRef, must create a UIFont first. really strange!

  3. Daniel Bonates,

    Hi, you save my weekend! Just with one sentence: “Core Text is really just a text drawing engine”… Incredible, but so many info just showing how to draw, but no info saying that this the ONLY capability of this framework, so, as I saw a demo running on WWDC about coreText (session 110) that the guy click and select frames show a red bounding box, I was wondering on how he did this, and was trying to find a way to give my users just one simple facilitie: select text. Now I know that he must be using some trick from apple cave, and thats could explain why, just the sample code from this session, wasnt on Sample Code Pack from WWDC…

    In time, can I ask you if you know about any trick to simulate a selection of text, like standard UITextview or UIWebview?

    Thanks for so great and objective info :)

  4. Hi Daniel, Glad to help! You could try attaching a gesture recognizer to your view, and then pass the location of the event to the CTLineGetStringIndexForPosition function. Take a look at the documentation, as this function returns the index of the corresponding string in a particular CTLineRef (or kCFNotFound). Doing that, you might know which text was selected, and then you can change the properties of that particular piece of text. Everything’s in the documentation. Good luck!

  5. Daniel Bonates,

    Hum, now Im wondering: - can I get any CTLineRef even if I used CTFrameDraw? - or should I draw lines using CTDrawLine sand retain any line reference?

    Can you help me?

    Thanks in advance ;)

  6. Sway,

    I am looking for a library where I can create an ebook – whereas I can display pages in a book, have swipe/curl effects to go between pages, etc… The big challenge here is to then have a settings page where the users can change the ‘font’ or ‘font size’ and it will redraw each page of the book and have the page numbering changed (i.e. larger font mean less text per page). Also want to embed hyperlink and images (so those can adjusted too).

    Can this wrapper do that? If so – any examples? Thanks in advance :-)

    • This component could definitely be used for that, but you will have to write the code to read the ebook file (there are many formats out there) and all the controller interaction for the font sizes and types. As for the hyperlinks, that it is not possible with this wrapper.

      • Sway,

        Adrian,

        Thanks for the reply. Do you have any suggestions / recommendations of code / frameworks I could use/reuse to create this book app?

        I have text (I can get it in any format) and it will have images and links in it. I need to be able to display it as pages (views) like a book – and fit the correct amount of text in each page depending on the font/font size that user sets / changes in their settings.

        I see lots of book readers (i.e. stanza) etc..and need to create one myself for a self-contained book that has other features in it.

        Thanks again for your suggestions/recommendations. I would think there has to be some source code out there – since there are lots of book apps.

        Thanks, Sway

  7. Erdem,

    Hi, This is the best solution for my app on iPad. Thank you. I need to add images on top of second column but i couldnt find how can i do. Have you got any idea about that ?

    Thank You.

  8. pluto,

    As I noticed, our code is leaking like crazy. Have you run it in the instruments? Any solution at this moment? I am also trying to locate the leaks, and hopefully I can do that…

  9. Parvez Qureshi,

    Is it possible to incorporate CTRunDelegate in your wrapper because it seems a very nice rendering of rich text. Though CTRunDelegateCallbacks is not fully functional [at least that is my observation] because it does not create the necessary empty space for inserting images in between the text

  10. Parvez Qureshi,

    Thanks Adrian for your quick reply. Please let me know about your end results regarding CTRunDelegate as we fail to use at our end owing to its incomplete responsiveness

  11. Paul,

    Thanks for the wrapper. It is a big help. I am experimenting with it and my problem is a real slow down in performance for large files comparable to books (e.g. as in iBook). Can you instruct me on how to optimize the code for such files? Thank you, Paul

    • You should probably only load one multi column view at a time, or two at most. Then, when you scroll, reposition the views and re-calculate the page contents. This wrapper does not do this, but in any case, you must not load all the contents of the book in memory at once!

      • Paul,

        Hi Adrian, I worked on your directives and the project is coming together. Thank you very much for your prompt response and for the wrapper. It has been a big help in learning how to use CoreText on the iPhone. Paul (I find it works well loading three views: one being displayed and the other one or two on each side; then one can scroll the view and later load a new page; the iphone handles that memory w/o any problem; the breakdown actually occurred around 20 pages.)

  12. Actually you can use UIAppFonts feature in iOS 3.2 or higher to use embedded fonts in your applications. No need to extend UIFont class.

  13. Joshua,

    This is brilliant and has been a great help to me! One question however, how would I make the scroll view scroll downwards like a normal UIScrollView rather than left/right using pages?

    Thanks, Josh.

    • Thanks Joshua! At the moment the UIScrollView places all the multi column text instances horizontally, so the only thing to do for that is to change the layout of those instances in a horizontal fashion. Change the contentSize property accordingly and you’ll be set. I’ll add that in a future version as an option in the interface of the class.

  14. Gonso,

    Cool framework!

    I considering using it in a App and will totally give you credit for it!

    Question: Is there a way to have text in bold mixed with other text? I mean to have some text, then a bold line, then more text.

    Thanks! Gonso

    • Thanks to you Gonso! At the moment the interface only takes plain NSStrings, but in a future version I plan to add support for any NSAttributedString. This way you will be able to style your text as you want and have it displayed in several columns and pages.

  15. DJ,

    Nice work!

    One thing though, the program does too many loads which causes it to hang if the text gets big. It’s fine for a hew page text, but it wouldn’t work for say… a book. Do you think you can come up with a way to load it just once, but use it like a book while being able to change fonts and stuff? or would it be impossible to change fonts without loading the text into the fram everytime?

  16. Markus,

    Hi,

    probably thats the html extension for NSAttributedString on ios you are searching for ?

    https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML

    Markus

  17. Noam,

    Hi Adrian. Great work. I will use it for sure!! my plan is to create the opposite direction (i need it in order to use right-to-left languages). Is there an easy way (or couple of tips you can give me) in order to reverse the columns in each page and the scroll direction (start at the end and scroll the opposite way). This is a real saviour for me, cause until now i had to use uiwebview, which are memory consuming and real pain in the ass (i had to do css+html+js in order to achieve what you’ve done here). will appreciate any help. Thanks Noam

  18. Knet,

    Its very strange but the class AKOMultiColumnTextView in iOS 3.2 run perfect but in 4.0 (or greater) doesn’t work in some cases, it’s that possible?

    • I haven’t had that problem, sorry.

      • Verni,

        I also have this issue. It works perfectly on 3.2 but above 4.0 it gets hung at CTFramesetterCreateFrame (in my case).

      • Verni,

        Moresover, I have a library that has a test app within and where there is no problem with the multicolumntextview, but when I try and use this library from another app I experience the problem told above.

        I can’t assure that this happened also using XCode3 and I’m afraid it might be something related to XCode4 project settings…

        Any clue?

  19. Ahsan,

    Hi Andrian you are the man!! great work!!

  20. Ahsan,

    Just one question regarding custom fonts, I want multiline label with custom font. Any hint how to do it?

    Thanks!