NSTimer on device is slower than in simulator - iphone

I am new to iPhone development. I used [NSTimer scheduledTimerWithTimeInterval:0.01] for game loop. The game consists drawscreen function in which I use CGContextClipToRect to clip the large images for animation.
But the speed 0.01 seconds is working in simulator only not on device. How can I overcome this problem?
The timer code is in view controller as
(void)viewDidLoad {
GameView *main = [[GameView alloc]
initWithFrame:[[UIScreen mainScreen] applicationFrame]];
main.backgroundColor = [UIColor blackColor];
self.view = main;
[main release];
self.tim = [NSTimer scheduledTimerWithTimeInterval: 0.01
target: self selector: #selector (gameloop:) userInfo: nil repeats: YES];
[super viewDidLoad];
}
Anyone can help me?

NSTimer is the wrong tool for this job. It's not meant to be a real-time timer. It has no guarantees on when it will fire, and you can miss frames easily.
There are a lot of good recommendations for how to develop this kind of program on this thread. Note particularly the references to Apple's sample code.

As U62 said, 100fps is not a realistic expectation, try running it at 30, maybe 60 updates a second and see how it runs. Also if your writing a game that need to run at a high frame rate you should look into writing it in OpenGL.
One option may be to process logic every tick, but only draw to the screen every few ticks.

i mean ,for example when i animate frames ,frames are shown in correct speed in simulator.
but in device it shows very slow(FPS)in other words a boy runs fastly in simulator.but in
device he walks.

Related

loading 60 images locally fast is it possible...?

when my app starts it loads 60 images at a time in UIImageView
and it also loads a background music.
in simulator it works fine but in IPAD it crashes..
-(void)viewDidLoad
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//img.animationImages = [[NSArray arrayWithObjects:
MyImages = [NSArray arrayWithObjects:
//[UIImage imageNamed: #"BookOpeningB001.jpg"],...... B099,nil];
//[NSTimer scheduledTimerWithTimeInterval: 8.0 target:self selector:#selector(onTimer) userInfo:nil repeats:NO];
img.animationImages = MyImages;
img.animationDuration = 8.0; // seconds
img.animationRepeatCount = 1; // 0 = loops forever
[img startAnimating];
[self.view addSubview:img];
[img release];
[pool release];
//[img performSelector:#selector(displayImage:) ];
//[self performSelector:#selector(displayImage:) withObject:nil afterDelay:10.0];
[self performSelector: #selector(displayImage) withObject: nil afterDelay: 8.0];
}
-(void)displayImage {
SelectOption *NextView = [[SelectOption alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:NextView animated:NO];
[NextView release];
}
Am i doing anything wrong ?
Is there any other alternative to load the local images faster in
UIImageView !
I was doing something similar. Even if you quit all of the other apps on your iPad and manage to get it to run it will crash on you randomly.
I fixed this by preload very small (like 5 or 6 k) gif images. Then when my user entered an area where the big image needed to be seen I loaded the full res pic as a jpg and released the object as soon as they were done with it.
Now my app no longer has an issue on the simulator or the device and I do not have to have the user close everything.
If something crashes on the device but not on the simulator 9/10 times is your app has received a few memory warnings and forced to quit.
This Theory can be tested easily in two ways. First is to Log something to console in the appDelegates Memory Warning event method and secondly, when you run the app in the simulator, open the activity monitor and view the memory usage of the app by name.
The golden rule is that you should use as low a res of an image that you can get away with.
Rohit, is right in saying that pre-loading smaller images is one way to solving this problem provided that your not leaking, but this solution is only suitable for certain apps.
Lazyily loading media is generally how you should do this. There is no reason why you should have to load any more than 3 full res (full screen) images at any one time in an iPad app if you implement a decent memory efficient design.
In the case where you are doing something like a slide show for exmaple, you should be only be loading the focused image + 1 image each side into memory, destroying out of scope images as you go. Using a UIScrollView makes this easy with events that fire when scrolling has started, occurring and ended.
Speed improvements can be made by using CATitledLayer's, mutithreading any image tasks you can (GCD and blocks) (getting UIKit contexts are now thread safe too).
Good luck there are plenty of examples of all of these things accessible via the apple documentation or a quick search.

Animation in OpenGL ES view freezes when UIScrollView is dragged on iPhone

I have an animated transparent OpenGL ES subview (a modification of Apple's template EAGLView class) which draws a rotating sphere. Just like Apple's example, CADisplayLink is used on devices where available.
On the same screen, there is a UIScrollView containing UIButtons that can be selected. When the user scrolls the UIScrollView, the animation of my EAGLView freezes. This behavior is reproduced on iOS Simulator 4.2 and on iPhone OS 3.1.3 on an iPhone 2G device.
Any ideas on what to do to prevent pause of the EAGLView, apart from coding my own scroll view?
Whether CADisplayLink fires during scrolls depends on the mode with which you add it to the run loop. Probably you have this, somewhere:
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
UIApplication adds a run loop mode, UITrackingRunLoopMode, for 'tracking in controls', which includes when a scrollview is scrolling. So at that point the runloop is switched out of the default mode and hence your display link (and also any timers, NSURLConnections, etc, added in the default mode) will fail to fire until default mode is restored.
Quick fix: change your code to:
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
UITrackingRunLoopMode is considered one of the common modes.
Spending too much time interrupting UIKit can lead to some very poor control responsiveness, so you need to be careful. It'd be to diverge from the topic massively, but although OpenGL is modal and therefore not particularly threading friendly, you can use an EAGLSharegroup to do rendering on a separate thread and then push it onto the main thread.
An example in (2016) Swift3...
let d = CADisplayLink(target: self, selector: #selector(ThisClassName.updateAlpha))
d.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)
//and then, for example...
func updateAlpha() {
let a = leader.layer.presentation()?.value(forKey: "opacity") as! CGFloat
follower.alpha = a
}

iphone threading question - looping?

i want to have a background thread in my app that changes an image every 5 seconds for as long as the app is being run. Can someone point me in the direction of how this works? I am new to threads.
If you are using UIImageView and want an animated change between images you do not even need a timer. UIImageView can animate between images all by itself:
NSArray *images = [NSArray arrayWithObjects: [UIImage imageNamed: #"foo.png"],
[UIImage imageNamed: #"bar.png"],
nil];
yourImageView.animationImages = images;
yourImageView.animationDuration = 5.0s;
[yourImageView startAnimating];
The details are documented in the UIImageView docs.
An NSTimer will probably do what you are looking to do, however, calls from NSTimer will normally block the main thread, if the process is involved, or you need to getting something from the internets to switch out the picture, you will need to create a new thread to do this.
For information on threading, I highly recommend the CS193P Lecture on performance, They go into detail on NSThread, NSOperations, ect.
Also, from Apple, Threading programing Guide.
You can use an NSTimer for this. No need to spawn off e new thread:
[NSTimer scheduledTimerWithTimeInterval:5.0s target:self selector:#selector(updateImage) userInfo:nil repeats:YES];
You do not need a thread for that. You can do it with a timer which is simpler than a thread. See the timer programming guide.

iPhone CGRectMake memory consuption

On iPhone.. Why would code such as this cause memory leak? after 2 minutes the net bytes have doubled.
All I'm doing is moving a ball round the screen with an NSTimer calling the below method.
Any ideas?
- (void)nextFrame:(NSNotification *)notification {
ballInstance.frame = CGRectMake(value, 0, 320, 480);
}
here is the 'full' code, new project, still behaves the same. It moves a jpg accross the screen, and as it does memory is massively consumed. If I remove the '++' from 'value' memory is fine. (in otherwords have a static graphic) So.... is the image being cached is the question?
If so how can i stop it reaching astronomical sizes?
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window makeKeyAndVisible];
NSTimer * nSTimer =[NSTimer scheduledTimerWithTimeInterval: .02
target: self
selector: #selector(tick)
userInfo: nil
repeats: YES];
value =0;
}
- (void)tick {
NSLog(#"tick");
myOutlet1.frame = CGRectMake(value++, 0, 320, 480);
}
The posted code has no leak. The problem is elsewhere.
If you know that there's a leak inside of nextFrame:, it has to be in -[Ball setFrame:] because it is the only message sent in this method.
The leak is not in the code you show, especially if frame is a #synthesized property. You either need to show more code, or spend some quality time with Instruments to figure out what is being leaked and where it is being allocated.
According to Apple:
This is a bug in iPhone OS 3.0. The allocator for the graphics system
is reporting realloc events as malloc events, so ObjectAlloc tallies
these as new objects that are almost never being freed. I'm not
certain why you might not see it when you add the Leaks tool, but
neither tool would show a true leak for this.
Though I'm still none the wiser as to how to remedy it.
I've posted a complete sample application that seems to more or less match your "new project" example above. Can you take a look at it and see if this gives you any ideas? I've run it on the simulator and on the device w/ no leak.
http://static.fatmixx.com/MemTestApp.zip
It really does look like there is NO leak here. I'm building against iPhoneOS 3.1 - Debug.
Sujal

How can I fix 'sticky' touchesMoved in my openGLES app?

I have my openGL scene rendering using the detach thread method
//This is at the end of my init method
SEL selector = #selector(preMainLoop);
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:selector object:nil];
[thread start];
[thread release];
}
-(void) preMainLoop
{
while (isRunning) {
NSAutoreleasePool *loopPool = [NSAutoreleasePool new];
[self performSelectorOnMainThread:#selector(mainLoop) withObject:nil waitUntilDone:YES];
[loopPool release];
}
}
When I start getting touch events, I want to update my scene accordingly. But it seems like the scene is updating much faster than the iPhone is registering the touch events. For testing I'm trying to just drag a box around the screen based on the current position of a UITouch (updating the position during touchesMoved). I also have another box that moves independently, unaffected by touches.
The indepent box moves around smoothly, at a nice 60 frames per second. The touch box has 'jerky' movement which leads me to believe that the render loop is shoving out touch events or something to that affect.
Any help appreciated!
This forum thread has a long discussion comparing and contrasting NSTimer vs. MainLoop. In particular, I think you are looking for the following:
//Yield to system calls (touches, etc.) for one ms.
while( CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002, FALSE) == kCFRunLoopRunHandledSource);
However since you are doing this on the same single thread as everything else, I personally doubt you will be seeing any performance improvement over a properly configured NSTimer, and you may even take a hit. Your mileage may vary, but it might be worth testing both ways and doing some metrics before you launch. It's an easy enough thing to test.