zic*_*c10 12 detection motion ios
我有一个简单的问题.我试图检测用户何时摇动iPhone.我有标准代码来检测运动,这没有问题.然而,在我的实际手机上进行测试时,我意识到你必须非常努力地摇动设备才能触发运动检测.我想知道是否有办法实现一定程度的敏感性检查.例如,一种检测用户是否轻轻摇动设备或在轻微摇晃和硬摇动之间的某种方式的方法.这将针对iOS 7,因此非常感谢任何从旧iOS版本中弃用的提示或建议.我已经完成了我的谷歌搜索但尚未找到任何解决此问题的好方法(如果有的话.)
谢谢!
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    if(motion == UIEventSubtypeMotionShake)
    {
       //Detected motion, do something about it 
       //at this point.
    }
}
-(BOOL)canBecomeFirstResponder
{
    return YES;
}
-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self becomeFirstResponder];
}
-(void)viewWillDisappear:(BOOL)animated
{
    [self resignFirstResponder];
    [super viewWillDisappear:animated];
}
zic*_*c10 18
这是我找到的解决方案.这很好但你必须使用deviceMotionUpdateInterval时间值以及accelerationThreshold,这对于实际的"轻微摇动"与"拿起手机并将其移近您的脸部等"进行精细平衡可能很棘手......"可能有更好的方法,但这里有一个开始.在我的视图中,我做过这样的事情:
#import <CoreMotion/CoreMotion.h> //do not forget to link the CoreMotion framework to your project
#define accelerationThreshold  0.30 // or whatever is appropriate - play around with different values
-(void)viewDidLoad
{
      CMMotionManager *motionManager; 
      motionManager = [[CMMotionManager alloc] init];
      motionManager.deviceMotionUpdateInterval = 1;
      [motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]  withHandler:^(CMDeviceMotion *motion, NSError *error)
             {
                [self motionMethod:motion];
             }];
}
-(void)motionMethod:(CMDeviceMotion *)deviceMotion
{
    CMAcceleration userAcceleration = deviceMotion.userAcceleration;
    if (fabs(userAcceleration.x) > accelerationThreshold
        || fabs(userAcceleration.y) > accelerationThreshold
        || fabs(userAcceleration.z) > accelerationThreshold)
        {
           //Motion detected, handle it with method calls or additional
           //logic here.
           [self foo];
        }
}
使用核心动作.将您的二进制文件链接到CoreMotion框架.在你的班级中加入#import.创建CMMotionManager的实例.将deviceMotionUpdateInterval属性设置为合适的值.然后调用startDeviceMotionUpdatesToQueue.您将在块内获得连续更新,包括加速度,磁场,旋转等.您将获得所需的数据.要注意的一件事是,如果间隔太小,更新应该如此之快,因此你必须采用合适的逻辑来处理相同的事情.
这是一个基于zic10的答案的快速版本,添加了一个标志,即使在该处理程序中的第一行时,也会阻止对运动处理程序进行一些额外的调用motionManager.stopDeviceMotionUpdates().
此外,3.0如果您想忽略抖动,但检测到碰撞,则值的大小可能很有用.我发现0.3它太低了,因为它最终更像是"检测移动".在我的测试中,范围更像是:
这是Xcode单VC模板的完整视图控制器:
import UIKit
import CoreMotion
class ViewController: UIViewController {
    lazy var motionManager: CMMotionManager = {
        return CMMotionManager()
    }()
    let accelerationThreshold = 3.0
    var handlingShake = false
    override func viewWillAppear(animated: Bool) {
        handlingShake = false
        motionManager.startDeviceMotionUpdatesToQueue(NSOperationQueue.currentQueue()!) { [weak self] (motion, error) in
            if
                let userAcceleration = motion?.userAcceleration,
                let _self = self {
                print("\(userAcceleration.x) / \(userAcceleration.y)")
                if (fabs(userAcceleration.x) > _self.accelerationThreshold
                    || fabs(userAcceleration.y) > _self.accelerationThreshold
                    || fabs(userAcceleration.z) > _self.accelerationThreshold)
                {
                    if !_self.handlingShake {
                        _self.handlingShake = true
                        _self.handleShake();
                    }
                }
            } else {
                print("Motion error: \(error)")
            }
        }
    }
    override func viewWillDisappear(animated: Bool) {
        // or wherever appropriate
        motionManager.stopDeviceMotionUpdates()
    }
    func handleShake() {
        performSegueWithIdentifier("showShakeScreen", sender: nil)
    }
}
我用于此测试的故事板如下所示:
值得注意的是CoreMotion在模拟器中无法测试.由于这种限制,您可能仍然觉得值得另外实现检测运动抖动的UIDevice方法.这将允许您在模拟器中手动测试抖动,或者让UITests访问抖动以进行测试或使用fastlane的快照等工具.就像是:
class ViewController: UIViewController {
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        becomeFirstResponder()
    }
    override func canBecomeFirstResponder() -> Bool {
        return true
    }
    override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
        if TARGET_OS_SIMULATOR != 0 {
            if event?.subtype == .MotionShake {
                // do stuff
            }
        }
    }
}
然后使用Ctrl-Cmd-Z在模拟器中测试抖动.