2013-10-02 5 views
11

Ich habe eine einfache Frage. Ich versuche herauszufinden, wenn ein Benutzer das iPhone schüttelt. Ich habe den Standard-Code, um die Bewegung zu erkennen und das funktioniert kein Problem. Beim Testen dieses Telefons habe ich jedoch festgestellt, dass Sie das Gerät ziemlich stark schütteln müssen, damit die Bewegungserkennung ausgelöst wird. Ich würde gerne wissen, ob es eine Möglichkeit gibt, eine Empfindlichkeitsprüfung durchzuführen. Zum Beispiel, um festzustellen, ob ein Benutzer das Gerät leicht schüttelt oder zwischen leichtem und hartem Shake. Dies wird auf iOS 7 ausgerichtet sein, so dass alle Tipps oder Ratschläge, die von älteren iOS-Versionen nicht veraltet sind, sehr geschätzt werden. Ich habe mein googlen gemacht, aber habe noch keine guten Lösungen für dieses Problem gefunden (Wenn es welche gibt.)iOS Bewegungserkennung: Motion Detection Empfindlichkeitsstufen

Danke!

-(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]; 
} 

Antwort

6

Kernbewegung verwenden. Verknüpfen Sie Ihre Binärdatei mit CoreMotion Framework. Fügen Sie #import in Ihre Klasse ein. Erstellen Sie eine Instanz von CMMotionManager. Setzen Sie die Eigenschaft deviceMotionUpdateInterval auf einen geeigneten Wert. Rufen Sie dann startDeviceMotionUpdatesToQueue auf. Sie erhalten fortlaufende Aktualisierungen innerhalb des Blocks, einschließlich Beschleunigung, Magnetfeld, Rotation usw. Sie erhalten die Daten, die Sie benötigen. Eine Sache, die beachtet werden muss, ist, dass das Update so schnell sein sollte, wenn das Intervall zu klein ist, und daher müssen Sie geeignete Logik verwenden, um dasselbe zu handhaben.

+0

Vielen Dank, das hat mir sehr geholfen, ich werde eine Lösung veröffentlichen, die ich nach Ihrem Post und einigen anderen googling implementiert habe, die mich zum selben Ort geführt haben. – zic10

+0

Gut zu wissen, dass es Ihnen geholfen hat –

+0

ist es möglich, Erschütterungsereignis zu erkennen, wenn die App im Hintergrund ist –

17

Hier ist die Lösung, die ich gefunden habe. Dies funktioniert gut, aber Sie müssen mit dem GerätemotionUpdateInterval Zeit Wert sowie die accelerationThreshold spielen, die schwierig sein kann, um einen feinen Balanceakt für einen tatsächlichen "leichten Shake" vs "nehmen Sie das Telefon und bewegen Sie es näher an Ihr Gesicht usw ... "Es könnte bessere Wege geben, aber hier muss man anfangen. Innerhalb meiner Ansicht didLoad habe ich etwas wie folgt aus:

#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]; 
     } 
} 
+0

Diese Methode motionMethod wird beim Schütteln des Geräts nicht aufgerufen – Dhara

+0

Haben Sie mit einbezogen application.applicationSupportsShakeToEdit = YES; in Ihrer DidFinishLaunchingWithOptions-Methode in AppDelegate.m? – zic10

+0

immer noch nicht angerufen :( – harshitgupta

5

Dies ist eine schnelle Version auf zic10 Antwort basiert, mit dem Zusatz einer Flagge, die ein paar zusätzliche Anrufe an Ihre Bewegung Handler selbst wenn die erste Linie verhindert bekommen in diesem Handler ist motionManager.stopDeviceMotionUpdates().

Auch ein Wert von etwa 3.0 kann nützlich sein, wenn Sie den Shake ignorieren, aber einen Bump erkennen möchten. Ich fand 0.3 viel zu niedrig, da es mehr wie "Bewegung erkennen" war. In meinen Tests waren die Bereiche mehr wie:

  • 0,75 - 2.49 ist eine bessere Reichweite für wackel Empfindlichkeit
  • 2,5-5,0 eine gute Auswahl für „ignorieren schütteln, erkennen Bump“ ist

dies ist die komplette view-Controller für eine Xcode einzelnen VC-Vorlage:

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) 
    } 

} 

Und das Storyboard ich für diesen Test verwendete sieht wie folgt aus:

enter image description here

Es ist auch erwähnenswert, dass CoreMotion im Simulator nicht testbar ist. Aufgrund dieser Einschränkung kann es sich dennoch lohnen, die UIDevice-Methode zur Erkennung von Bewegungsschütteln zusätzlich zu implementieren. Dies würde es Ihnen ermöglichen, Shake im Simulator manuell zu testen oder UITests Zugang zum Shake für Tests oder Tools wie fastlanes Snapshot zu geben.Etwas wie:

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 
      } 
     } 
    } 

} 

Und dann drücken Sie Strg-Cmd-Z-Shake im Simulator zu testen.

0

Heres, wie ich tat dies mit Swift 3.

Import CoreMotion und

import CoreMotion 
let motionManager = CMMotionManager() 

Auf ViewDidLoad eine Instanz erstellen oder wo immer Sie wollen nach Updates starten Überprüfung:

motionManager.startDeviceMotionUpdates(to: OperationQueue.current!, withHandler:{ 
      deviceManager, error in 
      if(error == nil){ 
       if let mgr = deviceManager{ 
        self.handleMotion(rate: mgr.rotationRate) 
       } 
      } 
     }) 

Diese Funktion nimmt die Drehrate und erhält eine Summe für die Absolutwerte für die X-, Y- und Z-Bewegungen

func handleMotion(rate: CMRotationRate){ 
     let totalRotation = abs(rate.x) + abs(rate.y) + abs(rate.z) 

     if(totalRotation > 20) {//Play around with the number 20 to find the optimal level for your case 
      start() 
     }else{ 
     print(totalRotation) 
     } 
    } 

func start(){ 

//The function you want to trigger when the device is rotated 

}