Should I save strings returned by NSLocalizedString()? - iphone

I'm working on an iPhone app that we're localizing in both English and Japanese for our initial release. We frequently call NSLocalizedString() to load the appropriate localized string for display. Is it generally better to save the localized strings in instance variables for the next time we need them, or am I micro-optimizing here and should I just reload the string each time it's needed?

This is one of those "it depends" answers.
Calling NSLocalizedString involves performing a lookup in the bundle. These lookups are pretty fast but not free. Whether to cache this return value or just have the convenience of calling NSLocalizedString will depend on how it's used.
If you're passing the return to the
textfield of something like a
UILabel or UITableViewCell then the
lookup will only occur when you
first set the property.
If you're using it in a drawRect
call then the lookup will only
happen when your view needs to be
repainted which could be often,
infrequently, or never.
If your using it in a game UI where
the screen is redrawn every frame
then for a few UI elements these
lookups could be happening hundreds
of times each second.
I would say that for something like #3 you should start with caching the results.
For the others, write them in the way that's most convenient and if you have performance issues in your UI use Instruments to narrow down the cause. If it's NSLocalizedString then optimize it accordingly.

Micro-optimizing. First make it work, then make it right, then make it fast. And when you get to step 3, run Shark (or Instruments), then follow its guidance.

I suspect that you don't take too much of a performance hit. NSLocalizedString(key, comment) is a macro that converts to
[[NSBundle mainBundle] localizedStringForKey:(key) value:#"" table:nil]
Without benchmarking, I have no idea how expensive this is, but I suspect it's not too bad. My feeling is that this won't be a performance bottleneck for you, but you can always run Shark or Instruments and see for yourself when you run your application on the device.

Related

How bad is it for a UIView to hold information on the Model (Business Object)

This question is specific to iOS development.
Imagine you use UITableView and inside the UITableViewCells you show information regarding one or more of your application business objects through a bit more complex class that we'll call ComplexBOView.
Now you want to trigger a specific action when the user taps this view contained in your UITableCellView (the event can be triggered through a UITapGestureRecognizer)
Most of the time what is considered "best practice" is to use the tag property of the UIView to actually go back to your model and retrieve the correct business object.
This often is suitable but in some cases it can come very handy to hold a pointer to the business object used to built your ComplexBOView.
#interface ComplexBOView : UIView
{
UILabel* lblSummary;
// ....
UITapGestureRecognizer* tapGesture;
NSObject* businessObject_;
}
#property (nonatomic, readonly) UITapGestureRecognizer* tapGesture;
#property (nonatomic, assign) NSObject* businessObject;
The idea behind this, is to actually directly go back to the businessObject when the user tapped the view.
Two questions here
Is it really bad to have NSObject* information inside the UIView ?
Should this information be retained meaning the relationship between the view and the model becomes here much stronger (ownership of the view towards the object) ?
Thanks for your advice.
The general advice is
Views don't own data!
and it's a good advice. It can save you a lot of trouble in the long run. But what does own mean? If you look at a UIButton or a UILabel, the button has a title the label a text property. So they are holding some data, they have to - the alternative would have to have a delegate that is asked for the text every time they get drawn.
So what does that mean in your case? Well that depends. If your ComplexBOView is just generic view that is specifically designed to display your specific business object, it wouldn't be the worst to hold that object in a property of it (just my opinion).
Of course you loose the possibility to easily reuse that view with a different model, but maybe that isn't an option anyway, because it's so specific. Of course you could move all that code from the ComplexBOView to the controller. But as you said then you also have to maintain a connection between each model object and the appropriate view. (Btw. I wouldn't use the tag to do that, it's better to just use an `NSDictionary instead)
On the other hand Trausi and Michael do have valid points. If you break that "rule" this one time, you might get loose and break it on every other occasion and before you know it, you end up with lots of custom views each holding a reference to some part of your model. In the long run you might make changes to your model (maybe in ways you never expected in the first place - and trust me, that is going to happen more often than not) and then you have to go to every single subclass and adjust them. Of course if that model-specific code lives in your controller you also have to modify all of that, but at least it's all in one place.
So to sum up, those best practices, advice and design patterns are there for a good reason. They proved themselves useful in countless cases. So in general you do good by just following them. There are however cases where it might be worth violating them, but you have to have some very good reasons and you should be aware of the consequences.
Ultimately, it's your code, your design, your decision. Maybe you guess wrong, but some lessons have to be learned the hard way. Next time you know what to do and, more important, why. Making your own experiences is always valuable.
You should stick to the delegate design. You never know when you might need help with the code and people expect to use a delegate. This would spaghetti-fy your code in my opinion.
Remember that Views get recycled, especially in tableviews. Once the view is out of sight, it is re-used, so any logic you put in there would be complicated to maintain to say the least
Trausti Thor is right. As soon as you begin that kind of short cut, it's the death of a thousand compromises (or to put it another way, the technical debt just heaps up until it the resulting code base is so scary no one wants to touch it in case they break something else).
Whenever you have the chance to do it right, first time, do it, because there will be times when commercial, or other, pressures force you to do otherwise and these are unavoidable but you want to minimise the impact of such compromises by making them the exception.
Finally, if it's an exception, almost a blot on your code, you are probably going to be more inclined to go back and fix it during quieter times.

Best scenario to avoid memory leaks on iOS

I'm building an application that reads rss files something like Bing or Pulse, so I've built a class (UIViewController) that shows each individual entry in the feed and a class that contains that list of entries and another class that shows all the feeds at once, and I've not used any xib files so I've implemented a method in each class that gets called after each rotation to reset the frames of the views inside that class. But I'm facing a problem in the memory especially when calling that method when a rotation happens knowing that it just assigns a CGRect to each frame in the view.
So could you please help me to avoid this problem or suggest a different way to avoid it, and am I right about not using xib files or should I use them when ever I can and set the rotation thing inside them (using the auto resizing mask).
And if there is some complex free example like those applications, could any body point me to it.
Any help would be greatly appreciated,
and thanks in advance...
First, there is no reason to avoid nib files when they are useful to you. They are often useful. There is no reason to use nib files when they are not useful to you. If you have complex layout, they are definitely very useful. Whether to use them or not, however, is a personal choice based on the particular application. As a beginner, I would recommend using them and getting comfortable with them, and particularly relying on the Xcode templates to set them up correctly.
Nib files aren't your issue, one way or another here. You're leaking memory, and you need to investigate why. First, run the static analyzer to make sure there are no obvious errors. Then run your app under Instruments (Leaks) and look for large leaks. Then run your app under Instruments (Allocations) and look for what's eating the most memory. That should point you to your error.
The most likely cause, without any insight into your code, is that you are misusing ivars. Make sure that you access your ivars through accessors (except in init, dealloc and in the accessors). Directly accessing your ivars is the #1 cause of memory problems in iOS.
Release the objects properly which has been allocated and defined globally. Do not release the object of your UIViewController when it is active. Most of the leakage problems occur by releasing the object of the UIViewController before it reaches out of scope.

Is there any performance loss when repeatedly calling UIGraphicsGetCurrentContext

I'm building a UIView with a custom drawRect function. This is a fairly complex view, with a number of different items that need to be drawn. I've basically broken it down into one function per item that needs to be drawn.
What I'm wondering is should I pass my CGContextRef, obtained from UIGraphicsGetCurrentContext(), as a parameter to each function, or can I just call it at the start of each function? The latter option looks neater to me, but I am wondering if there is much of a performance penalty?
It's the same, unless you are saving/restoring context all around. In any way, getting the context from that method will, most probably, never be the bottleneck.
I suggest that if you are not saving and restoring states, you could use the UIGraphicsGetCurrentContext(). However, if you are indeed saving state, you should pass this one since it would be easier to read your code.
It's a matter of style I guess...
Pier-Olivier's response is good, and just grazes the key issue: don't worry about it until you have to. This is a case of premature optimization. Before spending a lot of time deciding whether to pass around your CGContextRef, you should write your application and then look at the performance. Using Instruments can help you figure out where your real bottlenecks are. If it turns out this is causing problems (which I highly doubt), then you can optimize it.
just profile after it's implemented correctly and well tested.
if it really shows up as a hotspot, then your problem is likely best divided, and/or rendered to an offscreen context... or by using lower level rendering.

Do I lose performance by using .xib files to provide an iPhone app's GUI?

I was wondering if there is a difference between using .xib files for GUI design and doing this programmatically.
As it is a compiler I would assume that there is no relevant time lost.
Am I wrong?
(Note: Tapping this out on my phone, so I apologize ahead of time for any weird formatting or grammar - if there are issues, I'll fix them when I'm back at my laptop.)
I've done some quick, dirty, and extremely informal tests to check this out for myself, and here's what I found (note that the app I built for the tests was just scratch and not necessarily representative of a "real" app):
Startup time was faster when when the initial screen was a nib
For all subsequent screens, performance increased when coding the UI by hand
It's odd at first, but when you think about it, maybe it isn't really all that strange.
The startup issue confuses me, but I assume it's because Apple, being Apple and being obsessed with startup times (in a good way, of course), just optimized the phone's unarchiver in such a way that loading from an archive (nib) can be faster than coding by hand.
That said, most people write apps that aren't going to be significantly affected by any differences. My (again: quick and dirty) tests showed that, from a cold start (you haven't run the app yet or in a while), the nib-based app consistently loaded its initial screen about twice as fast as the hand-coded version. While that sounds like a big deal, we're talking just a few milliseconds. That difference will be imperceptible to users. For a warm start (you've already opened and closed the app), the differences for startup time were much smaller.
For this reason, I like to use nibs for laying out the foundation of an app: any top-level navigation (tab controllers, nav controllers, etc.), and then code the rest of the UI by hand.
Plus, because the iPhone UI is so specific to, well, the iPhone (surprise!), coding UIs by hand isn't difficult the way it is when writing desktop apps. You use the same UI components over and over - once you've got that down, whipping up a UI in code is easy. You don't have eight-billion widgets to choose from as you would developing a Windows/OS X/whatever application. The iPhone's consistency makes it the easiest platform I've developed against in ages when it comes to hand coding UIs.
I've also found that NSCoding (which is what I use for persisting state across app runs) is much easier to work with when I've hand-coded a UI. I've run into problems where a nib-based screen wouldn't properly archive because of UIImage instances. UIImage (at least the last time I checked) doesn't conform to NSCoding, so the archive process dies (and a rather unpleasant death it is). I used UIImage as an example here, but anything the archiver tries to store that doesn't conform to NSCoding is going to foul up the process, so that's something to think about.
Another time I always code UIs by hand is whenever I'm using a dynamic table. If I'm creating a static table - one whose cells will basically never change - nibs are fine. For any other kind of table, and especially those that have, say, thumbnails and other resource-intensive bits, the control I get when coding by hand makes it possible to get performance you aren't going to get with nib-based table cells. For that, you do have to skip CocoaTouch and work directly with CoreGraphics, but the performance improvements you can make are worth every last line of code you have to write. For examples of table performance from projects I've worked on, see the Barnes and Noble Store (not the ebook reader) and Style.com. We built a framework for those (and other) apps, and the secret to the smooth table scrolling is that we never once used cells loaded from nibs (it's more complex than that, but skipping nibs was the first step to getting the performance you'll see in those apps).
Generally speaking, possibly the most important thing to consider when using nibs is that you need to break your UI up across files. That is, don't stick your app's entire UI into a single nib. When a nib is being loaded, it's the whole thing - there might be a view in the nib your users will rarely, if ever, see, and those get loaded just like everything else, sucking up resources for no reason. If you don't use separate nibs for each of your app's screens, it's easy to run into memory and performance issues.
To further clarify: if you have an app with five view controllers, stick each controller in its own nib. You don't want to load anything until its needed. There are exceptions to this, but that's simply how coding is - given enough time, you'll find a reason to do something "the wrong way," but the a-nib-for-each-screen approach is the way you ought to be doing it unless you have a good reason not to.
I'll leave it there - I hope it helps a little.
Just remember:
My informal mucking around showed that startup was faster with a nib (as long as you keep the nib as simple as possible, keeping only what you need in it).
After startup, performance seemed to improve for hand-coded UIs.
If done correctly, and if you aren't writing a game or something, nibs shouldn't result in perceptible performance issues.
In my experience, tables are different - they're one place I will rarely use nibs.
If you're using NSCoding for persisting app state, nibs can be problematic, and any workarounds probably aren't worth the effort since coding iPhone UIs by hand is relatively easy.
Keep your nibs as simple as possible - I can't say this enough. Wherever possible, create a nib for each screen of your app rather than stuffing your entire app's UI into a single nib.
Ok. Stopping for real this time.
Hope this helps :)
Very little. There are some exceptions. For example, if you use a xib to load the image that goes into a UITableViewCell, then that could be a problem since UITableViews with many cells are sensitive to loading times. However, for all intents and purposes, there should be no noticeable performance hit.
The information in the xib does have to be decoded at runtime and loaded into memory, which is not as fast as just creating UI elements programmatically and directly.
Beware premature optimization, especially when it involves writing a great deal more code than you need to.

How much does an CGAffineTransformMakeRotation() cost?

Is that an very cost-intensive function that sucky my performance away under my feet? I guess they used that one for the waggling buttons on the home screen + core animation. I just want to know before I start wasting my time ;)
Seems unlikely that it'd be much of a performance problem - it works out to something like a Cosine, a Sine, and a few multiplications. Don't call it thousands of times a second, and you'll be fine.
Very (very) little. This is also something you can easily measure yourself; see the following URLs for examples/information on implementing high-resolution timing:
http://developer.apple.com/qa/qa2004/qa1398.html
http://code.google.com/p/plinstrument/source/browse/trunk/Source/PLInstrumentTime.h
http://code.google.com/p/plinstrument/source/browse/trunk/Source/PLInstrumentTime.m
http://code.google.com/p/plinstrument/
Like with everything, it depends on how and how much you use it. It's used all the time in game development, which the iPhone is very well suited for. CoreAnimation is also very fast. If you're worried about it, my suggestion is to take one of the Apple-provided sample apps and run it through Instruments to preform some of your own benchmarks to see if they are acceptable for your needs.
All CGAffineTransformMakeRotation() does is fill in the matrix for a regular old CGAffineTransform. If you think you can fill (or pre-fill) the matrix faster yourself, then go for it (I'd be really surprised if this wasn't super-optimized already).
Then when it comes time to do the actual work of applying the transform, I'm pretty sure the GPU is told to take care of it so it'll run fast and your main CPU shouldn't take too much of a hit.
If you're really worried about it, then do the transforms in 2D space on top of OpenGL to make sure it's hardware optimized.
I just want to know before I start wasting my time
Optimise the system not the individual lines. Who knows how many times your code will call the transform. Better to get the whole system working, profile it and then optimise the parts that are too slow.
Don't worry about individual calls that people tell you are slow. Use this information as a pointer if your code is slow but always see how the operate in your code.