We have an app in AppStore Bust~A~Spook we had an issue with. When you tap the screen we use CALayer to find the position of all the views during their animation and if you hit one we start a die sequence. However, there is a noticeable delay, it appears as if the touches are buffered and we we receive the event to late. Is there a way to poll or any better way to respond to touches to avoid this lag time?
This is in a UIView not a UIScrollView
Are you using a UIScrollView to host all this? There's a property of that called delaysContentTouches. This defaults to YES, which means the view tries to ascertain whether a touch is a scroll gesture or not, before passing it on. You might try setting this to NO and seeing if that helps.
This is a pretty old post about a seasonal app, so the OP probably isn't still working on this problem, but in case others come across this same problem and find this useful.
I agree with Kriem that CPU overload is a common cause of significant delay in touch processing, though there is a lot of optimization one can do before having to pull out OpenGL. CALayer is quite well optimized for the kinds of problems you're describing here.
We should first check the basics:
CALayers added to the main view's layer
touchesBegan:withEvent: implemented in the main view
When the phase is UITouchPhaseBegan, you call hitTest: on the main view's layer to find the appropriate sub-layer
Die sequence starts on the relevant model object, updating the layer.
Then, we can check performance using Instruments. Make sure your CPU isn't overloaded. Does everything run fine in simulator but have trouble on the device?
The problem you're trying to solve is very common, so you should not expect a complex or tricky solution to be required. It is most likely that the design or implementation has a basic flaw and just needs troubleshooting.
Delayed touches usually indicates a CPU overload. Using a NSTimer for frame-to-frame based action is prone to interfering with the touch handling.
If that's the case for your app, then my advice is very simple: OpenGL.
If you're doing any sort of core-animation animation of the CALayers at the same time as you're hit-testing, you must get the presentationLayer before calling hitTest:, as the positions of the model layers do not reflect what might be on screen, but the positions to which the layers are animating.
Hope that helps.
Related
I'm looking for help with a performance issue in an Objective-C based iOS app.
I have an iOS application that captures the screen's contents using CALayer's renderInContext method. It attempts to capture enough screen frames to create a video using AVFoundation. The screen recording is then combined with other elements for research purposes on usability. While the screen is being captured, the app may also be displaying the contents of a UIWebView, going out over the network to fetch data, etc... The content of the Web view is not under my control - it is arbitrary content from the Web.
This setup is working but as you might imagine, it's not buttery smooth. Since the layer must be rendered on the main thread, there's more UI contention than I'd like. What I'd like to do is to have a setup where the responsiveness of the UI is prioritized over the screen capture. For instance, if the user is scrolling the Web view, I'd rather drop frames on the recording than have a terrible scrolling experience.
I've experimented with several techniques, from dispatch_source coalescing to submitting the frame capture requests as blocks to the main queue to CADisplayLink. So far they all seem to perform about the same. The frame capture is currently being triggered in the drawRect of the screen's main view.
What I'm asking here is: given the above, what techniques would you suggest I try to achieve my goals? I realize the answer may be that there is no great answer... but I'd like to try anything, however wacky it might sound.
NOTE: Whatever techniques need to be App Store friendly. Can't use something like the CoreSurface hack that Display Recorder used/uses.
Thanks for your help!
"Since the layer must be rendered on the main thread" this is not true, as long as you don't touch UIKit.
Please see https://stackoverflow.com/a/12844171/136305
Maybe you can record at half resolution to speed up things, if that fits the requirements?
I'm displaying a series of images on an iPad that are being sent over a network connection. It seems to work fine, but the images have a lot of ghosting for some reason (see image below). Is there some kind of technique for drawing that would eliminate this? I'd say it's an issue with the refresh rate of the screen, but that wouldn't explain why using the iPad's screenshot functionality captures the phenomenon.
You are probably switching between images in a way that triggers an implicit animation that cross-fades between the old image and the new one.
The documentation for layer actions explains how CoreAnimation is deciding to run that implicit animation, and how to override it.
The two easiest ways IMHO are:
When you change the image, use a CATransaction to disable actions
In your layer's delegate, implement -actionForLayer:forKey: and return [NSNull null].
(If you are using a UIView, it's already the layer's delegate.)
This question gives a few more options -- it might even be a duplicate of your situation.
I have multiple UIView animations running in my app. They are very short, and then make callbacks to a method that then usually fires off another animation. This leads to a lot of little animations running at the same time, each firing back callbacks.
This actually performs pretty well, and for the first few levels (the app is a game), no problems are observed. However, as you continue to play deeper into the game, I'm starting to get memory warnings and ultimately crashes. I've put NSLog in all of my dealloc methods, so I can see that everything is being properly released and dealloc'd. I've also run static analysis on the app and fixed anything it found.
The weird part to me is this: Shouldn't any performance problems caused by running multiple animations be processor bound (i.e. shouldn't I see a bunch of slowdown and such)? It seems that everything performs just fine, it just runs up memory too fast and there's nothing more I can free. Is there something in the framework on the UIView side of things that will need lots of memory to do these operations? Is there perhaps a leak in the framework I need to avoid when doing these?
Additional note: I'm animating a custom class that extends UIView and has a label and a UIImageView inside of them.
Multiple animation shouldn't cause memory warnings..
I suggest you should run Instruments for Leaks, ObjectAlloc & CPU Samplers..
That would give a much better view than NSLogs in dealloc
You don't show any code so it's hard to give specific advice, however, have you considered using Core Animation layers instead of UIViews? If you need to animate text, you'll have to use a view since there is no CATextLayer on the phone, however, Core Animation provides the facilities to draw complex sprites in a 2d space making it a great candidate for many games.
Best Regards.
I have an scroll view with some sophisticated animations happening during scrolling. Although after 2 weeks of finetuning the performance is acceptable now, the scrolling is not 100% smooth when the animations happen.
I know that core animation does animations in a background thread. But I wonder if it would help to split those animation blocks (10 of them at pretty much the same time) into threads.
There are a few methods that look interesting:
– performSelector:onThread:withObject:waitUntilDone:
– performSelectorInBackground:withObject:
or is that nonsense to do?
No, it won't help. As you correctly stated yourself, Core Animation already runs in a seperate thread. Core Animation is smart enough to handle animation blocks as efficiently as possible. I wouldn't advise interfering with it.
The Core Animation Programming Guide says:
An abstract animation interface that
allows animations to run on a separate
thread, independent of your
application's run loop. Once an
animation is configured and starts,
Core Animation assumes full
responsibility for running it at frame
rate.
Are you sure the choppy behavior is really from CA? Do you have anything else going on?
If you have any background network access, consider moving that into a separate thread - the time taken to service those calls takes away from time the UI spends updating the screen as you scroll.
The 'info' button in Interface Builder shows me that there are dozens of 'Illegal Geometry' warnings, each one with the issue 'This view overlaps one of it's siblings.' Is this anything to be worried about? Will it stop the app being accepted by Apple? The errors are happening because I'm layering PNGs over each other when I make the interface.
It should be fine. I have an app with the same warnings that was accepted with no problems.
The issue is that overlapping siblings are not allowed if the views are not backed by Core Animation layers (default on the desktop). On the iPhone, all UIViews are backed by CoreAnimation layers, so the overlapping is acceptable. As stated in the documentation for UIViews (2nd paragraph, last sentence): "Sibling views are able to overlap without any issues, allowing complex view placement."
Not a problem, as long as you're aware it's happening.
Of course, there are probably better ways of doing things. If your images aren't going to be moving, it might make more sense to compose them into one larger image and just use that one. If they are going to be moving, it might make more sense to just add them programmatically.
But this is your code, and you'll have a better idea of what you're expecting than I will.
If the views are not opaque, keep in mind that you will copositing them together at runtime which will incur a performance penality. If these appear on a view that needs to scroll I would want to make sure that they are opaque or not overlapping, otherwise I would not worry to much.