Methods to determine time spent 'drawing' by UIImageView? - ios

In my app I see terrible performance when I add some custom components to a UIImageView. It's most likely the aforementioned custom components and they will need to be improved upon, but I'd like to be able to measure said improvements down the road. I'd also like to see how many times the UIImageView is drawn during the animation of a particular view.
One strategy that I've kicked around is subclassing UIImageView (only for the purpose of benchmarking) and having overridden 'draw' methods in my subclass log something and then call the super class's method.
This would be fine, save for drawRect won't be called for subclasses of UIImageView. Are there 'drawing' methods for UIImageView that I could override in this manner?
In theory, I could accomplish something similar by substituting a subclass of UIImageView with a subclass of UIView, but this will become a bit more invasive and I'd only like to do this as a last resort.
Finally, am I down a rabbit trail and there's a really obvious solution (or tool) staring me in the face? I know Instruments can provide some profiling in terms of frame rates in this area, but I don't see a solution to my problem with my limited knowledge of the tool.

Use Instruments.
It's made for these things. You even said it yourself.
The "Instruments User Guide" is a good place to start if you've never used it before.
Learning how to use instruments is time well spent. You will always have use for it when performance tuning your app, looking for memory leaks, etc.
If you really are determined to know the execution time of a method then you could have a look at DTrace. It's very powerful but a much harder than Instruments. You can also use it to build your custom tools in Instruments.

Related

Is it possible to give more memory to an object in Swift or Objective-C?

I find that UITextView's become sluggish when you add more than 1MB of text. Outside of complex custom work, such as re-creating UITextView, is it possible to somehow allocate more memory or some other trick to an object?
Allocating more memory to UITextView isn't going to help you. It's already taking all the memory it wants. If there were a simple trick with no tradeoffs, then UITextView would almost certainly just do that automatically. So it depends on what tradeoffs you want and what features you're using. For instance, you may get some improvements by removing features like data detectors. Or using only unformatted strings (rather than attributed strings with complex formatting). Not allowing editing may improve things. Of course if you need those features, then that's not helpful (but you haven't explained what you're doing). If you're implementing delegate methods, then of course the problem could certainly be in your methods rather than UITextView. I somewhat doubt these tweaks are going to change a lot, but turning off features is the best place to start.
1MB does seem like a lot of text for a UITextView. It's not really its common use case and opens up some difficult layout issues, especially if there is any formatting going on. It also represents a difficult user experience for navigating (does your scrollbar really work effectively on a 500 page document?) I'd almost certainly be looking at a custom solution (possibly built on TextKit) to take care of this fairly custom problem.

UIView animation vs gif. Which one should I choose if I want to get better performance?

I have a UITableView. I am adding a loader on each of its cells with custom animation. It is just an image of a ball which keeps bouncing.
Will adding a gif lead to better performance, or is using CABasicAnimation, like I am currently doing, a better option?
Thank you.
CABasicAnimation is a fine way of doing this. CA runs very close to the metal on iOS and you will get good performance out of it.
Practically speaking, performance considerations are probably not very important for this scenario, as the animation you describe shouldn't stress any modern iOS device. But if you've already got it implemented in CoreAnimation, I would definitely advise sticking with that.

Can I have complete control over UIKit?

I've been frustrated by the lack of extensibility categories give the developer. I cannot override getters or setters, let alone define new properties. The question is:
"Is it possible to do these things WITHOUT subclassing a UIKit component like UIView?"
Subclassing UIView has its disadvantages, too. I cannot force components of UIKit that subclass UIView (e.g. UIImageView) to instead subclass my subclass of UIView. Categories really do work best for what I'm adding to the UIView class, but the limitations I stated earlier are too restricting for my tastes.
Any help would be great!
Without answering how to do it, I can refer to an interview with Loren Bricther:
He built his own version of the user interface framework, the software
that sits right above the graphics processor on an iOS device. Apple
creates that for developers — it was completely unnecessary for him to
do this. But this is the kind of thing he considers “fun.”
“It’s insane,” he admitted. “But I wanted to experiment with different ways of driving graphics … Apple’s [UIKit] is the best, but I wanted to try.” The experiment was a resounding success — and now has a million guinea pigs testing his code via Letterpress. And, he said, “there have been zero issues” with what he built.
So it is possible. Letterpress is built this way.

iOS: How to make the CADisplayLink's event called BEFORE actual screen draw?

I'm building a cross platform UI library's iOS implementation using UIKit, one of the library's primary function is allow user to change the child control's size freely, and the parent control's size will automatically adapt.
Since refresh the parent's size everytime when a child's size changed is inefficient and unnecessery, so I designed the UI system to refresh all "dirty" control's position, size, and a lot of things before actual device draw/render happen. On iOS, I use CADisplayLink to call the refresh method, then I discovered the event was called AFTER everything has presented onto screen, that caused the following problem:
User will see a "crashed" layout first. (The render happens first)
After a short period (CADisplayLink's event triggered), everything will return to normal.
At first I thought my way of using CADisplayLink is wrong, but the solution cannot be found anywhere, so I'm quite despaired right now (I'm going to hang my self!!)
Or maybe I shouldn't use CADisplayLink at all?
Please Help me!
PS. Since I'm building a cross platform thing I'm actually using MonoTouch, but I believe the basic concept is same.
PS2. And since I'm using MonoTouch, which is C#, so the description above may not fit in the Objective-C world (like the word "event", I think the Obj-C relevant is selector, or something ^_^)
PS3. Also please pardon my poor English, feel free to ask me any questions if my description isn't clear enough.
Codes here:
CADisplayLink _displayLink = CADisplayLink.Create(Update); //Update is my refresh method
_displayLink.AddToRunLoop(NSRunLoop.Current, NSRunLoop.NSDefaultRunLoopMode);
Should be easy enough to understand ^_^
From all the information of what I can gather, is that basiclly there is no way of doing that. So I have modified my layout code, which now apply the properties immediatly after a value is set. Some optimization still required, but no need to rely on CADisplayLink anymore.
Thanks anyway!

IOS memory and battery management - Memory vs Work

I am new to IOS and coming from pcs I am trying to get a feel for managing memory and battery resources.
I have a UIImageView subclass which is is very light (it's an image placeholder with a handful of methods). This subClass is repeatedly added to, and removed from, several root views. I hold an IBOutlet reference to the subClass on each root view.
Would you:
Simply add/remove the subClass from the root view (and keep it in memory)?
Or
Create and destroy the subClass instance each time (freeing the memory but extra work)?
Is this worth considering or am I worrying over nothing?
Would your answer be the same if the UIImageView subClass was very large?
Is there a way of measuring these matters?
In general, you can use UIImageView with disregard on iOS. UIImageView is not much more than a clipping region with some methods for dealing with images.
The resource which takes up more memory is the UIImage contained by the UIImageView and these are cached by iOS.
So there is little cost to creating UIImageViews and destroying them, just take care that you dealloc them and don't leak memory and you should be fine unless you have hundreds of them.
The subclass being "large" doesnt matter, the code in a class is never loaded more than once. If the class has alot of extra state - that will take up some memory but I cant image a whole lot of that in a UIImageView.
You better just keep it in memory. User experience will be much better if you don't slow down the device by continuously recreating the image view. One single poor UIImageView instance is not memory heavy enough to worth the time and effort to recreaty all the time.
Keeping it an memory to improve performance isn't as much of a hit as you would think - taken from the other answers you have. But you should remove it from memory if you get a memory warning, and provide a way to bring it back to life as needed.
I would go with your first option, keeping it in memory. This is just because I think it is handy to keep my views alive and reuse them. This means that they will remember their state and content and that helps out in many cases. I usually write methods to reset the content or refresh it when needed.
Keeping it in memory might also increase the loading of the view slightly, but usually you do not notice the difference, and I see people using both ways.
And yes, I would say you are worrying a bit too much, especially if you think this decision would affect battery.
Regarding memory management, keeping the imageview in memory or releasing/recreating consumes the exact same amount of memory as long as you only have one imageview that you are using. The only difference is that you are allocating and releasing it repeatedly if you are recreating it.
You could however get memory issues if you start creating new imageviews every time the user opens them and never letting go of them, but that means you are doing something fundamentally wrong in your programming.
As long as you know what you are doing, no need to worry about the amount of memory in a case like this - there's plenty. Start worrying if you are handling large images.
Especially if you use ARC there is not much to worry about, just start hacking away. If you are managing memory manually, I do recommend trying to reuse stuff because that causes less headache and risk of giant leaking. Use leaktools and analyze tool to make sure in this case.

Resources