【问题标题】:Why am I not reading any magnetic field values with this simple code?为什么我没有用这个简单的代码读取任何磁场值?
【发布时间】:2012-07-30 22:49:57
【问题描述】:

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

【问题讨论】:

    标签: iphone objective-c ios magnetometer


    【解决方案1】:

    调用startDeviceMotionUpdates方法后,磁场值不立即可用。您需要稍后尝试检索该值(即使用NSTimer 并检查更新。

    虽然这应该可行,但这不是一个好习惯。如果您只需要磁场值,您应该查看CMMotionManager 的文档并使用startMagnetometerUpdatesToQueue:withHandler: 的方法,如下所示:

    [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);
    }];
    

    干杯, 安卡

    【讨论】:

    • 我会尝试,但我不想使用磁力计数据的原始值,而是使用 deviceMotion 处理后的校准数据,如:NSOperationQueue *myQueue = [[NSOperationQueue alloc] init]; CMMotionManager *motionManager; motionManager = [[CMMotionManager alloc] init]; [motionManager startDeviceMotionUpdatesToQueue:myQueue withHandler:^(CMDeviceMotion *motion, NSError *error){NSLog(@"Value of X : %F",motion.magneticField.field.x)} 这段代码可以工作吗?
    • 我试过了(我也编辑了我的原始帖子以反映我所做的更改),应用程序没有崩溃,但我什么也没得到。控制台上甚至没有日志输出。
    • 你好,使用下面的操作队列[NSOperationQueue currentQueue],别忘了用motionManager.deviceMotionUpdateInterval = 1.f/10.f;设置更新率。
    • 我已将我的帖子重新编辑为我正在使用的当前代码,但我仍然一无所获。抱歉,我对 Obj-C 还很陌生.. :)
    • 代码while(!self.stopButtonPressed) 是不必要的,因为该块将根据您的更新间隔重复调用。你可以使用if(!self.stopButtonPressed)。还可以尝试使用NSLog(@"--------------> %i %i", motionManager.deviceMotionActive , motionManager.deviceMotionAvailable); 检查运动管理器的状态,并查看磁力计是否可用。
    【解决方案2】:

    您需要保留CMMotionManager。所以为它创建一个实例变量。例如:

    游戏.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);
                                                 }
         ];
    }
    

    问题在于,您正在创建的CMMotionManagerplay 方法结束时被释放,因为没有任何东西保留它。因此,处理程序永远不会因为您的运动管理器离开而被回调。

    【讨论】:

    • 你试过看startMagnetometerUpdatesToQueue:withHandler:吗?
    • 否,因为根据文档,它应该返回原始的偏置磁场值,而 DeviceMotion 类(或 CLLocationManager)返回已处理的无偏置值。
    【解决方案3】:

    顺便说一句,一种可能性是您正在运行的设备甚至可能没有磁力计。见magnetometer-for-compass-on-ipod-touch-4g我指向apple-devices-with-magnetometer的地方

    【讨论】:

    • 只是检查!它以前错过了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 2016-05-10
    • 1970-01-01
    相关资源
    最近更新 更多