I've read in the documentation that the NSString category method drawInRect is good for small amounts of text, but is too much overhead for large amounts. The alternative in my case would be to use Core Text CTFrameDraw.
My question is, what is the "cut-off" point between using drawInRect vs Core Text? Is Core Text always faster than drawInRect? If the extra programming is not the issue, should I always just use Core Text instead of drawInRect, even for small strings?
Mostly I'll be drawing paragraphs, but sometimes they can be short lines too.
For me it comes to use core text when I have some specific requirements from the graphic designer. For instance label that need to mix colors, type, font size etc. drawRect is method that draws something in a view layer, is just a wrapper around CG functions, core text is full framework to deal on how to draw text: change fonts, spaces, interlines.
I mean is not fair as a comparison, a better question could be when it comes to use core text instead of common UI text porpoise obejects and the answer is based on your app design-UI related requirements. Hope this helps.
I would write some test code to benchmark the two methods under consideration using your expected statistical distribution of string content. Maybe a timing a few tens of millions of string renders using each. Run the benchmarks on an actual iOS device, as relative performance may be different using the ARM targeted frameworks.
I wonder if using a UIWebView would get all the performance that's possible. The iOS (and every OS) has a constantly loaded webkit ready to go. Its pretty well optimized too. It would also get work offloaded.
Interesting to compare.
Related
I'm starting an investigation into downscaling an iPad application to fit into the form factor of the iPhone. The main problem is that this project does NOT use .storyboards or .xib files with the exception of a custom UIInputView.
My main question revolves around layout (obviously). Since all of the frame values are in the code, what is the best (shortest) way to allow for multiple different frames based on the total frame size?
I know this is very easy in a storyboard, but due to multiple developers and the use of SVN, we had to forgo the use of them during initial development.
I'm not seeing many resources on some google queries on the subject, most developers are going from iPhone -> iPad and not the reverse.
I know about this code:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
But I don't want to have do this for 500+ places in code where we set somethings' frame.
Would it be more efficient to extract all of the frame definitions to a class for retrieving device specific frame sizes?
Some additional notes, We're not using anything iPad specific other than popovers. The entire interface is mostly nested UIViews on one main UIViewController.
This is exactly one of the types of things that Auto Layout was meant to solve. Behind the scences, everything is using Auto Layout now, but if you have a lot of hardcoded constant values for sizes, you're in for a lot of work to actually take advantage of its new features.
If you want to avoid storyboards/xibs, I suggest considering refactoring your code not to use static sizes via frames/bounds (i.e. a lot of initWithFrame calls), but rather use Visual Format Language where ever you can, and dropping down to full on NSLayoutConstraints as needed.
You'll want to read and understand this: Working with Auto Layout Programmatically
With VFL, you can express virtually all of your sizes and positions as relative values. Where you cannot, you can pass in metrics to your VFL calls with the values that need to be explicitly set for iPad v. iPhone (where relative, calculated values do not work).
I'd like different words in a UILabel to be different colors. Does this mean each word will need to be a different UILabel? I'm guessing yes, though sure would be nice to just put color codes in the label somehow, you know? I guess I'm a bit spoiled by text markup in HTML.
There is no proper UIRichTextView in iOS. It's high on my wish-list for iOS 6 (and there's some reason to believe we may get it then due to the release of Pages).
Your options are to use multiple UILabel views, NSString UIKit Additions, Core Text, UIWebView, or one of a few third-party frameworks such as:
NSAttributedString-Additions-for-HTML
CoreTextWrapper
OHAttributedLabel
OmniUI
All of the current solutions have different problems. The most common problem is that it's hard to get select and copy functionality to work with rich text unless you use a web view. Web views are incredibly annoying because they're asynchronous and you have to do a lot of your interactions in JavaScript.
I wish there were a better answer.
(Obligatory shilling: This topic is covered in depth in Chapter 18 of iOS 5 Programming Pushing the Limits.)
UILabel doesn't support segmented formatting (the entire thing can only have one format).
Have a look at OHAttributedLabel, which does what you want.
As far as I'm aware you'd need to have separate labels for each different coloured word. Depending what you're trying to do you may be able to make use of myLabel.textColor to change the colour of the periodically or on events etc.
Aside from the WYSIWYG editor, what are the advantages of using XIB/NIB files over defining the layout in code in iPhone/iPad/iOS?
While I don't find XIB files much useful, many iOS developers do, which makes me suspect I might not know their benefits or how to use them properly.
Easier maintenance. More often than not, clients require last minute changes like changing the logo or changing colors or realigning something or some such. Much easier to change it in a xib file and see/show the results immediately
Decoupling. It forces you to write nicely decoupled code right from the offset, which again means easier maintenance.
Defining things in Interface Builder makes them much easier to adjust later. Also, doing interface elements in code can lead to a lot of code bloat, for setting things like exact placement, font, color, etc.
The main advantage using code directly gives you is speed. But it's usually better to start in IB and then see what might need speeding up.
Table cells are one of the main areas where you might consider drawing elements in code for speed.
Personnaly, I'm using XIB to see graphically my I'm doing so I don't have to run, check the look, change a bit the color, run the app, check... It allows me to get a better design. If you work with designer that gives you photoshop design, it will not be useful for you.
Second thing : when you start to really handle Xib, it's much faster than doing it with code (but it takes time and training for TableView and tableView cell for example)
What is the best way to use the custom UI graphics on the iPhone?
I have come across CGContextDrawPDFPage and Panic's Shrinkit. Should I be using PDF's to store my vector ui graphics and loading them using CGContextDrawPDFPage to draw them.
Previously I asked what way Apple store their UI graphics and was answered crushed png. The options are I can think of are below, but I'm also interested in any other techniques...
PNG (bitmapped image)
Custom UIView drawing code (generated from Opacity)
PDF (I've not used this method, is it with CGContextDrawPDFPage?)
This question is for vector graphics only (but I guess some people may only use bitmapped?). Looking for what is standard / most effective / most efficient.
Edit: Bounty added, I'm interested to hear the process of anyone who works with UI designers, or are themselves a UI designer. And pointers on resolution independence i.e. for iPad / iPhone HD future proofing.
Many thanks
Ross
I can suggest 3 different ways, 2 of which you already mentioned:
Creating custom UIView.
Drawing in a CGLayer.
loading from PDF.
Each have their advantages, depending on what you want to do:
UIView vs CGLayer
In terms of performance (for one-time drawing) and ease of use there shouldn't be much difference between the two (there are minor differences, but nothing serious). Apparently Opacity can export source code for both (I haven't personally used it). That said, there are things you should consider before choosing:
If you have a fixed image (which your question suggests so), use CGLayer. CGLayer objects will be cached on the graphics device, so re-using them is much faster. Even if the cache is cleared, you're still using the same object for redrawing, meaning there's no need for re-creating it.
On the other hand, if you need to change your drawing as the user interacts with the app, UIView could be faster, as you have the flexibility of updating just one part of the image instead of the whole view.
CGLayer is independent of the UI. So the same code works fine for Mac/iPhone/iPad, or even for saving to files.
Conclusion: Use CGLayer, unless it's a special case.
CGLayer (In code drawing) vs PDF (loading from file)
I don't have any benchmark for this, but I expect CGLayer to be slightly faster: (1) there's no need to read a file. (2) the pdf commands should be converted to system's graphic elements, which is more or less the same as creating a CGLayer. (3) I'm not sure about how pdf pages are cached, but I don't expect it to be faster than CGLayer. Anyway, all this shouldn't make much difference unless you want optimization till the last millisec. Again, the choice should be based on your use case:
CGLayer gives you more flexibility in the code. Your only access to a pdf page is through CGContextDrawPDFPage, which means even simple tasks such as scaling/transforming the drawing will be harder.
Using PDFs on the other hand, is more flexible after finishing the code. You can simply update the pdf file with a new whenever you want, load it from the web, etc. .
Creating a pdf could be easier than coding the drawing. You can use any app you want, you don't need to worry about the API and system resources. After all, the code can output a pdf file, not the other way around.
Conclusion: If you don't need to do much with the drawing (just want to show an icon or something), go with the pdf. if you need to work on it in the app, consider CGLayer.
Of course you could always mix the approaches as you see fit: e.g. Load a pdf file, put it in a CGLayer to adjust it, draw it with a UIView where you can put a badge on it!
I stumbled over this question because I have a question about PDFs too. I'm working together with a UI designer and we are succesfully using PDFs to create UI elements. For example: For a button we have 3 PDFs for ON, OFF and the shadow. I wrote a piece of code that transformes a PDF into a UIImage. It can scale the resulting image and even colorize it to have one template for many styles of buttons. It works pretty good :)
Our problem is that we can't scale up the vector graphics without quality loss. That's why we decided to use graphics that are big enough and we only have to scale them down. But I still wonder if there's a way to scale up a PDF before drawing it to a context and create a UIImage. Here's my post.
I want to implement a view in an iPhone application that is essentially like a rich text document. I need it to be click-editable, and I'd like to be able to embed graphic objects (either an overlaid view object, or manually drawn in graphic) with the text wrapping around. much like you would expect in a word processor. That's about the minimum functionality needed. Changing font for certain text would be a bonus (bold, size, etc).
UITextView would be a great start for me if it supported media like graphics embedded.
I'm still very new to Cocoa and Obj-C. Where should I start?
UITextView will not be nearly sufficient -- it has a very well-defined and simple functionality. That is an extremely complicated thing you're trying to do, wrapping text around an image -- you'll have to use to manually render the text in your drawRect method and do some very complex collision detection and calculate the string sizes etc. It's do-able, but extremely complicated.
Now, if you don't want the text to hug the image, but rather have the two appear on distinct lines, then you could fake this with a UITextView, then a UIImageView, then a UITextView, manually changing size and offset of each as the text changes...but this is a cheap hack and not exactly extensible. It could be sufficient for your needs, however.
UITextView does not allow rich formatting (bold, italics, different sizes, colors...), so that too would require a custom sort of text view.
Basically, it's a pretty big undertaking. If you're really committed, I recommend what Alex said -- get very, very comfortable with UIKit and Objective-C and iPhone coding in general. Then research how to make a rich text editor in other languages more suited to the functionality, and try porting that to the iPhone.
Hope this doesn't sound too discouraging. It's possible, but it won't be easy. And always bear in mind that the iPhone is a phone. Is it really the best platform for your application?
You might start with a much smaller, unrelated project. A viewer is no problem — start with UIWebView, which can render a RTF document for viewing. Creating a document editor, however, is no small task.