Stop gyro updates - ios

I cant work out to stop the Gyro updates in my Cocos2D game,
I have got the following code in my init: ` //gyro
motionManager = [[CMMotionManager alloc] init];
referenceAttitude = nil;
[motionManager startGyroUpdates];
timer = [NSTimer scheduledTimerWithTimeInterval:0.2
target:self
selector:#selector(doGyroUpdate)
userInfo:nil
repeats:YES];
Then in the gyro update itself I check when the progress is more than 100% if (progress > 100) {
[self pauseSchedulerAndActions];
[self stopGyroUpdates];
Then:
- (void)stopGyroUpdates{
NSLog(#"Stop gyro update");
}
but it keeps checking... So the code within the if statement keeps getting called.

I found the solution with the following code: `
-(void) callgyro:(int)gyroprocess {
NSLog(#"%i", gyroprocess);
if (gyroprocess < 100 ) {
motionManager = [[CMMotionManager alloc] init];
referenceAttitude = nil;
[motionManager startGyroUpdates];
timertwee = [NSTimer scheduledTimerWithTimeInterval:0.2
target:self
selector:#selector(doGyroUpdate)
userInfo:nil
repeats:YES];
}
else {
[motionManager stopGyroUpdates];
[timertwee invalidate];
NSLog(#"Gyro moet stoppen!");
}`
and within the gyro update itself:
if (progress > 100) {
[self callgyro:progress];
[self.timer invalidate];
self.timer = nil;
[Blikje setImage:[UIImage imageNamed:#"pop3.png"]];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setFloat:numhundreds forKey:#"score"];
progress = 0;
[self stopGyroUpdates];
}

Like rickster said, you need to call stopGyroUpdates on the CMMotionManager instance.so you need to create an instance variable or property in the interface implementation.
In your .m file where your declare the interface:
#interface ViewController ()
#property (strong, nonatomic) CMMotionManager *motionManager;
#end
Then initialize it as you require
motionManager = [[CMMotionManager alloc] init];
Then when you need to stop updates you call
[self.motionManager stopGyroUpdates]

You need to call stopGyroUpdates on your instance of CMMotionManager, not (or in addition to) on self. (This means that instance needs to persist beyond the scope if the method in which you call startGyroUpdates -- say, in a property or ivar -- if it doesn't already.)

Related

UIProgressView not updating for Audio Player?

The ProgressView is not updating while playing the song. By reading from other post i have used an update method to update at each time interval.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *filePath = [[NSBundle mainBundle]pathForResource:#"Fix you_Coldplay" ofType:#"mp3" inDirectory:#"Coldplay"];
NSLog(#"%#",filePath);
NSURL *url = [NSURL fileURLWithPath:filePath];
NSLog(#"%#",url);
musicPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
[musicPlayer prepareToPlay];
[trackProgress setProgress:0.0];
}
I have a play button which is also being used for calling updateTime: method.
- (IBAction)playButton:(id)sender {
[musicPlayer play];
[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
NSTimeInterval interval = musicPlayer.currentTime/musicPlayer.duration;
NSLog(#"%f",interval);
}
The updateTime: method
-(void)updateTime:(NSTimer *)timer {
trackProgress.progress = (musicPlayer.currentTime/musicPlayer.duration);
}
I am very new to programming and even stack overflow. This is the first question i am posting. Please help me and Thanks in advance.
First of all change timer value to:
//Change Value to 0.5 or 1 sec
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
Make sure you are setting trackProgress as 0 as initial value.
- (void)viewDidLoad {
[super viewDidLoad];
trackProgress.progress = 0.0;
}
Hope this will resolve your issue.
Make sure to update the progress view on the main thread
-(void)updateTime:(NSTimer *)timer {
dispatch_async(dispatch_get_main_queue(), ^{
self.trackProgress.progress = (musicPlayer.currentTime/musicPlayer.duration);
});
}
This might help. Create a Timer and add it to common runloop as shown below. Also keep a reference to timer so that it can be stopped later.
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

Managing Timers Passed as Variables

I am trying to perform what I thought was a simple task. I have a handful of repeating timers that need to be started and stopped.
I created methods for starting and stopping the timers, and attempt to pass the timers to the methods as parameters.
The problem is that the timers never seem to be stopped. Any ideas why this might not be working properly? Thank you!
Top of File:
#import "ViewController.h"
NSTimer *launchTimer;
NSTimer *transactionTimer;
Starting Method:
-(void) startingMethod {
NSString *urlString = #"http://google.com";
[[AsynchRequestService sharedInstance]
performAsynchronousURLRequest:urlString completion:^(BOOL success,
NSString *responseBody, NSString *responseStatus) {
if (success) {
[self stopResponseTimer:launchTimer];
}
else {
[self startResponseTimer:launchTimer
method:#selector(startingMethod)
interval:10];
}
}];
}
Method to Start the Timer:
-(void)startResponseTimer:(NSTimer *) timer method:(SEL) method
interval:(int) interval {
[timer invalidate];
timer = nil;
timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self
selector:method userInfo:nil repeats:YES];
}
Method to Stop the Timer:
-(void)stopResponseTimer:(NSTimer *) timer {
NSLog(#"STOP TIMER");
[timer invalidate];
timer = nil;
}
Make startResponseTimer and `stopResponseTimer' take the pointer to the object pointer intead.
-(void)startResponseTimer:(NSTimer **) timer method:(SEL) method
interval:(int) interval {
[*timer invalidate];
*timer = nil;
*timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self
selector:method userInfo:nil repeats:YES];
}
-(void)stopResponseTimer:(NSTimer **) timer {
NSLog(#"STOP TIMER");
[*timer invalidate];
*timer = nil;
}
then invoke it like
[self startResponseTimer:&launchTimer];
[self stopResponseTimer:&launchTimer];
This should make sure that you retain the right NSTimer object.
NOTE:It is always a good idea to check a pointer to a pointer to an object for NULL in a public method

Is there a way, in background, to get my app notified when the CMMotionActivity changes?

I'd like to know if the system can wake an application in the background if the CMMotionActivity changes, for example, if the user starts walking/running after sitting, I'd like to be able to execute some code and schedule a local notification.
Is there a way to ask the system to wake my app in the background for that ?
EDIT : By looking at the reference, it doesn't seem to be possible ("[...] and updates are not delivered while your app is suspended."), but maybe is there an other way ?
I solved this creating a background timer and checking for the activity type in the selector called method. Just have a look to the code in case it can be useful for you. I accept suggestions, corrections and advices over this.
#define k_timer_time 10.0f
#property NSTimer *timer;
- (void) createBackGroundTimerToCheckMotion{
// create new uiBackgroundTask
__block UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
__weak __typeof(self) weakSelf = self;
// and create new timer with async call:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
weakSelf.timer = [NSTimer scheduledTimerWithTimeInterval:k_timer_time target:self selector:#selector(onTick:) userInfo:nil repeats:YES];
weakSelf.timer.tolerance = 5;
[[NSRunLoop currentRunLoop] addTimer:weakSelf.timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
}
- (void) onTick:(NStimer*)timer{
if([CMMotionActivityManager isActivityAvailable])
{
__weak __typeof(self) weakSelf = self;
CMMotionActivityManager *cm = [[CMMotionActivityManager alloc] init];
CMPedometer *sc = [[CMPedometer alloc] init];
NSDate *now = [NSDate date];
NSDate *last30Sec = [now dateByAddingTimeInterval:-30];
[cm queryActivityStartingFromDate:last30Sec toDate:now toQueue:[NSOperationQueue mainQueue] withHandler:^(NSArray *activities, NSError *error)
{
[activities enumerateObjectsUsingBlock:^(CMMotionActivity *a, NSUInteger idx, BOOL * _Nonnull stop) {
//Your stuff here
}];
}];
}
else
{
NSLog(#"Error accessing Motion data");
}
}

cmdevicemotion stops providing update

I have some weird issue in my code that I can't figure out and need some help. I have defined a CMMotionManager in my AppDelegate. In my view controller, I define a property:
#property (nonatomic, retain) CMMotionManager *motionManager;
and then use this code to start the updates:
- (void)startMyMotionDetect
{
motionManager = [(AppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager];
motionManager.deviceMotionUpdateInterval = 1.0/60.0;
[motionManager startDeviceMotionUpdates];
timer = [NSTimer scheduledTimerWithTimeInterval:20/60 target:self selector:#selector(handleDeviceMotion) userInfo:nil repeats:YES];
}
However, the handleDeviceMotion get called only a few time and then it stops updating the deviceMotion output. I have changed the code to the push style (block code) but in that case the block is not getting executed! A test NSLog comment in the block never gets executed. Here is how that code looks like:
motionManager = [(AppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager];
motionManager.deviceMotionUpdateInterval = 1.0/60.0;
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *dMotion, NSError *error)
{
NSLog(#"test 1");
[self performSelectorOnMainThread:#selector(handleDeviceMotion) withObject:nil waitUntilDone:YES];
}];
Here is how the handleDeviceMotion code looks like:
- (void)handleDeviceMotion//:(CMDeviceMotion *)dMotion
{
if ([motionManager isDeviceMotionActive])
{
NSLog(#"test");
}
....}
With the first method, I see "test" printed a few times and then it stops.
I thought by retaining motionManager as a property, I don't have to worry about it being released but it appears that it is getting released somewhere (or do you think something else is going on?).
Many thanks for your help.

iOS Logic Unit Test target crashes after unit test passes with NSTimer

I want a timer class that can post messages to a delegate when there are 1/2/3 seconds to go.
My test target consistently crashes.
iOS logic unit test target.
Tests class that times a duration using a repeating NSTimer
One test with no asserts. The test passes, but then the target crashes with:
/Developer/Tools/RunPlatformUnitTests.include: line 415: 770 Bus error "${THIN_TEST_RIG}" "${OTHER_TEST_FLAGS}" "${TEST_BUNDLE_PATH}"
It seems to me that it's some kind of memory allocation error, but I can't figure out what I'm missing. The problem is associated with the stop timer routine somehow. It's only when the timer runs out that the target crashes.
Things I've tried
Build and Analyze - no errors reported
Remove -framework and UIKit from the linker flags
Removing dealloc - this has no effect
Test Code
-(void)testGivenThreeSecondDurationAtOneSecondDelegateShouldBeToldToShowGreenCard {
JGTimerController *timer = [JGTimerController timerWithDurationValue:1 delegate:nil];
[timer startTimer];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.1]];
}
Class Code
#interface JGTimerController : NSObject {
NSNumber *duration;
NSTimer *timer;
id <NSObject, JGTimerControllerDelegate> _delegate;
}
#property (nonatomic, retain) NSNumber *duration;
... public methods...
#end
#implementation JGTimerController
#synthesize duration;
+(JGTimerController *)timerWithDurationValue:(NSUInteger)durationValue delegate:(id <JGTimerControllerDelegate>)delegate_ {
JGTimerController *instance = [[[JGTimerController alloc] initWithDurationValue:durationValue delegate:delegate_] autorelease];
return instance;
}
-(JGTimerController *)initWithDurationValue:(NSUInteger)durationValue delegate:(id <JGTimerControllerDelegate>)delegate_ {
self = [super init];
timer = nil;
[self setDurationValue:durationValue];
_delegate = delegate_;
return self;
}
-(NSUInteger)durationValue {
NSNumber *result = [self duration];
return result ? [result intValue] : 0;
}
-(void)setDurationValue:(NSUInteger)value_ {
[self setDuration:[NSNumber numberWithInt:value_]];
}
-(BOOL)stopTimerAtZeroDuration:(NSTimer *)timer_ {
if ([self durationValue] == 0) {
[self stopTimer];
return YES;
}
return NO;
}
-(void)startTimer {
if ([self stopTimerAtZeroDuration:nil])
return;
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerDidCountDownByASecond:) userInfo:nil repeats:YES];
}
-(void)stopTimer {
if ([self durationValue] == 0 && [_delegate conformsToProtocol:#protocol(JGTimerControllerDelegate)])
[_delegate showRedCard];
[timer invalidate];
[timer release];
}
-(BOOL)timerIsRunning {
return (timer != nil);
}
-(void)timerDidCountDownByASecond:(NSTimer *)timer_ {
[self setDurationValue:[self durationValue] - 1];
[self stopTimerAtZeroDuration:timer_];
}
-(void)dealloc {
[_delegate release];
[timer release];
[duration release];
[super dealloc];
}
#end
There should be no [_delegate release] in dealloc because you did not retain it.
Likewise, timer should not be released. NSTimer is like every other NSObject, if you did not alloc, copy or retain, you do not need to release.

Resources