Ich möchte reagieren, wenn jemand das iPhone schüttelt. Es ist mir egal, wie sie es schütteln, nur dass es für den Bruchteil einer Sekunde heftig geschwenkt wurde. Weiß jemand, wie man das erkennt?
quelle
Ich möchte reagieren, wenn jemand das iPhone schüttelt. Es ist mir egal, wie sie es schütteln, nur dass es für den Bruchteil einer Sekunde heftig geschwenkt wurde. Weiß jemand, wie man das erkennt?
In 3.0 gibt es jetzt einen einfacheren Weg - haken Sie sich in die neuen Bewegungsereignisse ein.
Der Haupttrick besteht darin, dass Sie über UIView (nicht UIViewController) verfügen müssen, das als firstResponder die Shake-Ereignismeldungen empfangen soll. Hier ist der Code, den Sie in jedem UIView verwenden können, um Shake-Ereignisse abzurufen:
@implementation ShakingView
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if ( event.subtype == UIEventSubtypeMotionShake )
{
// Put in code here to handle shake
}
if ( [super respondsToSelector:@selector(motionEnded:withEvent:)] )
[super motionEnded:motion withEvent:event];
}
- (BOOL)canBecomeFirstResponder
{ return YES; }
@end
Sie können jede UIView (auch Systemansichten) einfach in eine Ansicht umwandeln, die das Shake-Ereignis abrufen kann, indem Sie die Ansicht nur mit diesen Methoden in Unterklassen unterteilen (und dann diesen neuen Typ anstelle des Basistyps in IB auswählen oder ihn beim Zuweisen von a verwenden Aussicht).
Im Ansichts-Controller möchten Sie diese Ansicht als Ersthelfer festlegen:
- (void) viewWillAppear:(BOOL)animated
{
[shakeView becomeFirstResponder];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[shakeView resignFirstResponder];
[super viewWillDisappear:animated];
}
Vergessen Sie nicht, dass Sie, wenn Sie andere Ansichten haben, die aufgrund von Benutzeraktionen zum Ersthelfer werden (z. B. eine Suchleiste oder ein Texteingabefeld), auch den Ersthelferstatus der erschütternden Ansicht wiederherstellen müssen, wenn die andere Ansicht zurücktritt!
Diese Methode funktioniert auch, wenn Sie applicationSupportsShakeToEdit auf NO setzen.
viewDidAppear
stattdessen meine Controller überschreibenviewWillAppear
. Ich bin mir nicht sicher warum; Vielleicht muss die Ansicht sichtbar sein, bevor sie alles tun kann, um die Shake-Ereignisse zu empfangen?motionEnded
bevor das Verwackeln tatsächlich aufgehört hat. Wenn Sie diesen Ansatz verwenden, erhalten Sie eine unzusammenhängende Reihe von kurzen Shakes anstelle eines langen. Die andere Antwort funktioniert in diesem Fall viel besser.[super respondsToSelector:
wird nicht tun, was Sie wollen, da es gleichbedeutend ist mit einem Anruf,[self respondsToSelector:
der zurückkehren wirdYES
. Was Sie brauchen ist[[ShakingView superclass] instancesRespondToSelector:
.Aus meiner Diceshaker- Anwendung:
Die Histerese verhindert, dass das Shake-Ereignis mehrmals ausgelöst wird, bis der Benutzer das Shake stoppt.
quelle
motionBegan
undmotionEnded
Ereignisse nicht sehr genau oder genau sind, um den genauen Beginn und das genaue Ende eines Shakes zu ermitteln. Mit diesem Ansatz können Sie so präzise sein, wie Sie möchten.Ich habe es endlich mit Codebeispielen aus diesem Undo / Redo Manager-Tutorial zum Laufen gebracht .
Genau das müssen Sie tun:
quelle
applicationSupportsShakeToEdit
istYES
.[self resignFirstResponder];
vorher anrufen[super viewWillDisappear:animated];
? Das scheint eigenartig.Erstens ist Kendalls Antwort vom 10. Juli genau richtig.
Jetzt ... wollte ich etwas Ähnliches tun (in iPhone OS 3.0+), nur in meinem Fall wollte ich es App-weit, damit ich verschiedene Teile der App benachrichtigen konnte, wenn ein Verwackeln auftrat. Folgendes habe ich getan.
Zuerst habe ich UIWindow unterklassifiziert . Das ist einfach peasy. Erstellen Sie eine neue Klassendatei mit einer Schnittstelle wie
MotionWindow : UIWindow
(Sie können auch Ihre eigene auswählen, natch). Fügen Sie eine Methode wie folgt hinzu:Ändern Sie
@"DeviceShaken"
den Benachrichtigungsnamen Ihrer Wahl. Speicher die Datei.Wenn Sie jetzt eine MainWindow.xib (Standard-Xcode-Vorlage) verwenden, gehen Sie dort hinein und ändern Sie die Klasse Ihres Window-Objekts von UIWindow in MotionWindow oder wie auch immer Sie es genannt haben. Speichern Sie die xib. Wenn Sie UIWindow einrichten programmgesteuert , verwenden Sie stattdessen dort Ihre neue Window-Klasse.
Jetzt verwendet Ihre App die spezialisierte UIWindow- Klasse. Wo immer Sie über einen Shake informiert werden möchten, melden Sie sich für diese Benachrichtigungen an! So was:
Um sich als Beobachter zu entfernen:
Ich habe meine in viewWillAppear: und viewWillDisappear: für View Controller eingefügt . Stellen Sie sicher, dass Ihre Antwort auf das Shake-Ereignis weiß, ob es "bereits ausgeführt" wird oder nicht. Andernfalls tritt ein Stau auf, wenn das Gerät zweimal hintereinander geschüttelt wird. Auf diese Weise können Sie andere Benachrichtigungen ignorieren, bis Sie wirklich fertig sind, auf die ursprüngliche Benachrichtigung zu antworten.
Außerdem: Sie können wählen, ob Sie abrufen möchten motionBegan vs. motionEnded abzurufen . Es liegt an dir. In meinem Fall muss der Effekt immer stattfinden , nachdem das Gerät im Ruhezustand ist (gegenüber, wenn es beginnt zu schütteln), so dass ich motionEnded . Probieren Sie beide aus und finden Sie heraus, welche sinnvoller ist ... oder erkennen / benachrichtigen Sie beide!
Noch eine (merkwürdige?) Beobachtung hier: Beachten Sie, dass dieser Code keine Anzeichen für eine Ersthelferverwaltung enthält. Ich habe dies bisher nur mit Table View Controllern versucht und alles scheint ganz gut zusammenzuarbeiten! Ich kann jedoch nicht für andere Szenarien bürgen.
Kendall et al. al - kann jemand darüber sprechen, warum dies für UIWindow so sein könnte ? Unterklassen ? Liegt es daran, dass sich das Fenster oben in der Nahrungskette befindet?
quelle
Ich bin auf diesen Beitrag gestoßen, als ich nach einer "erschütternden" Implementierung gesucht habe. millenomis antwort funktionierte gut für mich, obwohl ich nach etwas suchte, das etwas mehr "zittern" erfordert, um auszulösen. Ich habe den booleschen Wert durch einen intakeCount ersetzt. Ich habe auch die L0AccelerationIsShaking () -Methode in Objective-C neu implementiert. Sie können die erforderliche Menge an Schütteln anpassen, indem Sie die Menge an ShakeCount anpassen. Ich bin mir nicht sicher, ob ich die optimalen Werte gefunden habe, aber es scheint bisher gut zu funktionieren. Hoffe das hilft jemandem:
PS: Ich habe das Aktualisierungsintervall auf 1/15 Sekunde eingestellt.
quelle
Sie müssen den Beschleunigungsmesser über den Beschleunigungsmesser überprüfen: didAccelerate: Methode, die Teil des UIAccelerometerDelegate-Protokolls ist, und prüfen, ob die Werte einen Schwellenwert für die für ein Schütteln erforderliche Bewegungsmenge überschreiten.
Im Beschleunigungsmesser befindet sich ein anständiger Beispielcode: didAccelerate: -Methode ganz unten in AppController.m im GLPaint-Beispiel, das auf der iPhone-Entwicklerseite verfügbar ist.
quelle
In iOS 8.3 (möglicherweise früher) mit Swift ist es so einfach wie das Überschreiben der
motionBegan
odermotionEnded
Methoden in Ihrem View Controller:quelle
Dies ist der grundlegende Delegatencode, den Sie benötigen:
Stellen Sie auch den entsprechenden Code in der Schnittstelle ein. dh:
@interface MyViewController: UIViewController <UIPickerViewDelegate, UIPickerViewDataSource, UIAccelerometerDelegate>
quelle
Schauen Sie sich das GLPaint-Beispiel an.
http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html
quelle
Fügen Sie die folgenden Methoden in die Datei ViewController.m ein, damit sie ordnungsgemäß funktionieren
quelle
Es tut mir leid, dies als Antwort und nicht als Kommentar zu veröffentlichen, aber wie Sie sehen, bin ich neu bei Stack Overflow und daher noch nicht seriös genug, um Kommentare zu veröffentlichen!
Wie auch immer, ich möchte @cire als Zweites sicherstellen, dass der Ersthelferstatus festgelegt wird, sobald die Ansicht Teil der Ansichtshierarchie ist. Das Festlegen des Ersthelferstatus in Ihrer View Controller-
viewDidLoad
Methode funktioniert beispielsweise nicht. Und wenn Sie sich nicht sicher sind, ob es funktioniert, erhalten[view becomeFirstResponder]
Sie einen Booleschen Wert, den Sie testen können.Ein weiterer Punkt: Sie können einen View-Controller verwenden, um das Shake-Ereignis zu erfassen, wenn Sie nicht unnötig eine UIView-Unterklasse erstellen möchten. Ich weiß, es ist nicht so viel Ärger, aber die Option ist immer noch da. Verschieben Sie einfach die Codefragmente, die Kendall in die UIView-Unterklasse eingefügt hat, in Ihren Controller und senden Sie die
becomeFirstResponder
undresignFirstResponder
-Nachrichten anself
anstelle der UIView-Unterklasse.quelle
Zunächst einmal weiß ich, dass dies ein alter Beitrag ist, aber er ist immer noch relevant, und ich stellte fest, dass die beiden Antworten mit den höchsten Stimmen den Shake nicht so früh wie möglich erkannt haben . So geht's:
In Ihrem ViewController:
quelle
Die einfachste Lösung besteht darin, ein neues Stammfenster für Ihre Anwendung abzuleiten:
Dann in Ihrem Bewerbungsdelegierten:
Wenn Sie ein Storyboard verwenden, ist dies möglicherweise schwieriger. Ich kenne den Code, den Sie im Anwendungsdelegierten benötigen, nicht genau.
quelle
@implementation
seit Xcode 5Verwenden Sie dazu einfach diese drei Methoden
Einzelheiten können Sie über ein komplettes Beispielcode überprüfen dort
quelle
Eine Swiftease-Version basierend auf der allerersten Antwort!
quelle
Um diese App-weit zu aktivieren, habe ich eine Kategorie in UIWindow erstellt:
quelle