Question

Game.m

#import "Game.h"
#import "CoreMotion.h"

@implementation Game

- (id) init 
{
    self = [super init];

    self.stopButtonPressed = NO;

    return self;
}
-(void) play
{
     CMMotionManager *motionManager;
     motionManager = [[CMMotionManager alloc] init];
     motionManager.deviceMotionUpdateInterval = 1.f/10.f;
     [motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
                                        withHandler:^(CMDeviceMotion *motion, NSError *error)
                                        {
                                          NSLog(@"--------------> %i %i", motionManager.deviceMotionActive , motionManager.deviceMotionAvailable);

                                          NSLog(@"Degrees : %F",atan(motion.magneticField.field.y/fabs(motion.magneticField.field.x)) * 180.0 / M_PI);
                                        }
     ];
}

MyViewController.m

#import "MyViewController.h"
#import "Game.h"

@interface MyViewController()
{
    Game *game;
}
@end

@implementation MyViewController

-(void) viewDidLoad
{
    game = [[Game alloc] init];
}

- (IBAction)playPressed:(UIButton *)sender 
{
    // using a separate thread
    //[game performSelectorInBackground:@selector(play) withObject:nil];

    // not using a separate thread
    [game play] ;
}

- (IBAction)stopPressed:(UIButton *)sender 
{
    game.stopButtonPressed = YES;
}

@end
Was it helpful?

Solution

the magnetic field value is not available immediately after you call the method startDeviceMotionUpdates. You need to try to retrive the value in a later point (i.e. using a NSTimer and checking for updates.

Although this should work it isn't a good practice. If you only need the magnetic field value you should take a look at the documentation of CMMotionManager and use the method startMagnetometerUpdatesToQueue:withHandler: like the following:

[motionManager startMagnetometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMMagnetometerData *magnetometerData, NSError *error) {
  CMMagneticField field = magnetometerData.magneticField;
  NSLog(@"x: %f  y:%f  z:%f", field.x, field.y, field.z);
}];

cheers, anka

OTHER TIPS

You need to hold onto the CMMotionManager. So make an instance variable for it. For example:

Game.m

#import "Game.h"
#import "CoreMotion.h"

@interface Game ()
@property (nonatomic, strong) CMMotionManager *motionManager;
@end

@implementation Game

@synthesize motionManager = _motionManager;

- (id) init 
{
    self = [super init];

    self.stopButtonPressed = NO;

    return self;
}
-(void) play
{
     self.motionManager = [[CMMotionManager alloc] init];
     self.motionManager.deviceMotionUpdateInterval = 1.f/10.f;
     [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
                                             withHandler:^(CMDeviceMotion *motion, NSError *error)
                                             {
         NSLog(@"--------------> %i %i", self.motionManager.deviceMotionActive , self.motionManager.deviceMotionAvailable);
         NSLog(@"Degrees : %F",atan(motion.magneticField.field.y/fabs(motion.magneticField.field.x)) * 180.0 / M_PI);
                                             }
     ];
}

The problem is that your CMMotionManager that you're creating is being deallocated at the end of the play method since nothing is holding onto it. So the handler never gets called back because your motion manager has gone away.

BTW One possibility is that the device you are running may not even have a magnetometer. See magnetometer-for-compass-on-ipod-touch-4g Where I point to apple-devices-with-magnetometer

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top