GLKViewController: incorrect fps - iphone

Hope there are some GLKViewController experts out there because I have some problems :)
Just a quick description of my app. I have a UINavigationController in which I push different screens.
At some point, I get to my game screen which is a subclass of UINavigationController. In this screen, in viewDidLoad I manually create a EAGLContext, GLKView and instantiate a new GLKViewController (to handle my update&draw calls).
I am setting a preferred fps of 30.
The problem is that the first 3-4 update calls come with the correct DT, but then I have 2-3 frames with 1 second between them. I measure the DT using controller.timeSinceLastUpdate.
So I get like:
dt=0.33
dt=0.33
dt=0.33
dt=1.07
dt=1.05
dt=0.33
dt=0.33
After this, I get valid only DT times. I have no idea why those frames have that kind of delay. I measured the time it takes me in the update & draw method, and it's nowhere near 1 second.
Also, I'm not loading any textures/creating any geometry. Everything is done at loading since it is a rather small game.
Also, if I pop the game screen controller and then push back another instance of the game screen, this new GLKViewController will only call my update method aproximately every 1 second.
Did anybody have a problem with the framerate when using GLKViewController?
Thanks,

The problem is that you don't know what else the device is doing between your refreshes :)
You might only spent 0.1s working on the next frame but if there is a memory warning then other bits of your app will also take time to process. I guess that the gl controller will do it's best to keep to the preferred frame rate but if lots is going on in the background then there's not much it can do about it.
As long as you make sure that your code is rendering as fast as possible and isn't spiking in the same way as the framerate then it's not your render path. From your question it sounds like you've already tested that.
The other thing you might want to do is to watch out for other notifications that might be passed into your app (i.e. memory warnings).
Finally, is there a pattern to the slow frames - do they coincide with a new image being loaded or a file access? Have you done as much as possible beforehand? EDIT - rereading your question makes me think that you've already done this, sorry!
Sorry I can't be any more use :(

Ok, so I finally figured it out. It turns out that it's not even related to the GLKViewController (surprise surprise!).
It had something to do with the way I'm displaying the game screen view controller, like this:
GameAreaViewController* gameController = [[GameAreaViewController alloc] init];
[UIView beginAnimations:#"animation" context:nil];
[self.navigationController pushViewController: gameController animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
[UIView setAnimationDuration:0.7f];
[UIView commitAnimations];
SAFE_DEL(gameController);
If I use an animation duration of 0.3f, then I don't get any lag. At 0.5f sometimes I get it and at 0.7 I was always getting it.

Related

Tracking UIView frame change animation

I have a UITextView that changes it's frame with the animateWithDuration:animations method:
[UIView animateWithDuration:1.5 animations:^{
[_textView setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - keyboardSize.height-25)];
}];
Is there any callback that helps me track the height of the UITextView as it animates?
There is no accurate way.
That's because the frame is just set directly. The animation takes care of the transition, but actually there is no transition.
There are some ways of estimating what is the current frame size and for me, the best is the simple math solution using a timer, when the animation started and the animation duration.
But, again, it's probably for the best if you just go another way, as this is certainly going to impact on your code cost and precision.
It's my first post and I don't really know anything that well, just learning and trying to help.
This depends on what you want to do with this thing.
If you want somehow accurate information about your frame, use the presentationLayer. This is a semi-accurate representation of what's actually on the screen. Note that this is in the coordinates of the view (bounds), so you need to convert it to the superview's coordinate system to get the current frame.
CGRect currentTextViewFrame = [_textView.superview convertRect:[_textView.layer.presentationLayer frame] fromView:_textView];
Note however this will be about one drawing loop or more off. If you are trying to base another animation off this it may be problematic and can cause flickering or other delay-induced effects. Also, at least the official documentation says this may not always be very fast and you may want to make the animation yourself if you need this information often due to performance reasons.
[_textView.layer.presentationLayer frame].size.height;
Credit belongs to this anwser.

Prevent Splash Screen from showing after returning from background

I've noticed something that happens in every app i develop. It's usually not a concern but in this specific app it would be great if i could "fix" it, if it's even a bug.
Steps to re-produce the issue:
Start app , splash screen shows for approx. 3 seconds and app starts.
Press home button, app goes to background.
Bring app back from background (double clicking home screen and chosing it), shows the splash for half a second or so, and then the app goes back up .
Is it possible to get rid of that splash screen popping up for half a second on the way back from background? Its really a problem for this specific app.
I know that this question is marked an "answered" - but the reality is that the answer was not correct in my case and I want to share.
I initially came to the conclusion that the most accurate answer above was from QueyJoh - "this is something handled by iOS ... Short answer: it's out of your hands."
However after experimenting I managed to locate the issue as being entries in my info.plist file controlling the status bar. Specifically I had entries for "UIStatusBarHidden" and "UIStatusBarStyle".
Removing these entries from my plist file immediately stopped my app from showing the Splash screen when switching away from my app and back again.
Problem solved.
Matthew
Well, apparently this question wasn't very clever to begin with :)
This "problem" only happens in the Simulator. When Debugging on the device itself, it works as expected.
No harm done. Thanks everyone who tried to help! :)
In my experience, this is something handled by iOS (I'm going with experience because I've not seen any documentation about this). If the OS can restore the application state nice and quickly, it'll display a screenshot of its previous state while that state is restored.
However, if something will delay the process, such as the app not being in the background properly yet (such as during rapid task switching), or if something else predictable will delay the startup, then it reverts to the splash screen (instead of the screenshot), to ease the user experience.
Short answer: it's out of your hands.
I have this problem too,now I had solve it.The reason is you did too many things in applicationDidEnterBackground ,try to decrease .
Your code to display your splash screen should be in your appdelegate in the didFinishLaunchingWithOptions method. If it is then it only appears when your app actually starts up, not when it returns from the background.
Use something like this (I know it uses the old animation code but I 'm sure you can update it to blocks if you need to)...
splashView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, 320, 460)];
splashView.image = [UIImage imageNamed:#"Default.png"];
[myWindow addSubview:splashView];
[myWindow bringSubviewToFront:splashView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(startupAnimationDone:finished:context:)];
splashView.alpha = 0.0;
[UIView commitAnimations];
and then create a method called startupAnimationDone...
- (void)startupAnimationDone:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[splashView removeFromSuperview];
[splashView release];
}

Animate Train in iphone

I want to animate a 20 wagon train in iphone. The train will move left to right. Each wagon will have a different animation. I was confused how to do it. Because the images are large and 20 images at one time would cause memory warnings.
Can anyone suggest how to go about it. Should I use cocos2d for this?
Thanks!
I would do that in cocos2d.
I would create a 'Wagon'-class and then start by initiate two of them (just because I think that two wagons will fill the screen). And then start moving the wagons. Each time a wagon is completely out of the screen I would release it. When it's time for the next wagon I would initiate that and so on.
How many frames does the animations have, and how big are they? Maybe you'll have to make one atlas per wagon. You can always call:
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
and:
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
Cocos2D is best!
Create sprites, set actions to it and IMHO!!!
If you want to do using UIImageViews, look for
UIImageView.animationImages
UIImageView.animationDuration
UIImageView.animationRepeatCount
and
[UIView beginAnimations:(NSString *)animationID context:(void *)context];
[UIView setAnimationDuration:(NSTimeInterval)duration]
// make the changes in your view which you want to occur in given duration
[UIView commitAnimations];
But again, this will definitely give you a hard time, better go for Cocos2D.

Source of UIView Implicit Animation delay?

I have a block of UIView animation code that looks like this:
[UIView beginAnimations:#"pushView" context:nil];
[UIView setAnimationDelay:0];
[UIView setAnimationDuration:.5];
[UIView setAnimationDelegate:self];
[UIView setAnimationWillStartSelector:#selector(animationWillStart)];
view.frame = CGRectMake(0, 0, 320, 416);
[UIView commitAnimations];
The code basically mimics the animation of a ModalView presentation and is tied to a button on my interface. When the button is pressed, I get a long (.5 sec) delay (on iPod Touch...twice as fast on iPhone 3GS) before the animationWillStart: actually gets called. My app has lots going on besides this, but I've timed various points of my code and the delay definitely occurs at this block. In other words, a timestamp immediately before this code block and a timestamp when animationWillStart: gets called shows a .5 sec difference.
I'm not too experienced with Core Animation and I'm just trying to figure out what the cause of the delay is...Memory use is stable when the animation starts and CoreAnimation FPS seems to be fine in Instruments. The view that gets animated does have upwards of 20 total subviews, but if that were the issue wouldn't it cause choppiness after the animation starts, rather than before? Any ideas?
Try it with a single subview or with no subviews at all to make sure the delay is not caused by so many children.
Profile the code in Instruments to see where exactly the code lags. You might get down to some internal Core Animation function call that will hint you what’s going on.
Try the code without the “lot that’s going on” to make sure you’re not stepping on Core Animation’s toes with your other code.
Or, in short: experiment and measure, because conjectures seldom work when optimizing.
In your pasted block, you specify the selector animationWillStart (no colon), but later in your question, you refer to animationWillStart: (with colon). These selectors are not equivalent, so is it possible that your intended selector is never being called on account of this animation, and is being called 0.5 seconds later on account of some other animation?

Two related questions about iPhone autorotation

1) Is it possible to change the speed of autorotation on the iPhone?
2) Is it possible to time an animation to take place during the autorotation animation? I would like to resize a photo while rotation is occuring, rather than when it's done.
1) not that I know of
2) Yes, see this method:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
http://developer.apple.com/iPhone/library/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW53
As for the first question, I haven't used this but check it out:
[UIApplication sharedApplication].statusBarOrientationAnimationDuration = [NSTimeInterval ...];
See docs for UIApplication. The problem is that I don't know that this actually rotates the rest of your views. You may, however, be able to rotate the window's coordinate system around "manually" using UIWindow and [UIView beginAnimations ...] in order to recreate the whole effect.
Please post sample code somewhere if you get it working!