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
有帮助吗?

解决方案

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

其他提示

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top