Я хочу реагировать, когда кто-то трясет iPhone. Меня не особо волнует, как они его трясут, просто то, что его энергично размахивали на долю секунды. Кто-нибудь знает, как это обнаружить?
источник
Я хочу реагировать, когда кто-то трясет iPhone. Меня не особо волнует, как они его трясут, просто то, что его энергично размахивали на долю секунды. Кто-нибудь знает, как это обнаружить?
В 3.0 теперь есть более простой способ - подключиться к новым событиям движения.
Основная хитрость заключается в том, что вам нужно иметь некоторый UIView (не UIViewController), который вы хотите, чтобы firstResponder получал сообщения о событиях встряхивания. Вот код, который вы можете использовать в любом UIView для получения событий встряски:
@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
Вы можете легко преобразовать любой UIView (даже системные представления) в представление, которое может получить событие встряхивания, просто подклассифицируя представление только этими методами (и затем выбирая этот новый тип вместо базового типа в IB, или используя его при выделении Посмотреть).
В контроллере представления вы хотите установить это представление, чтобы стать первым респондентом:
- (void) viewWillAppear:(BOOL)animated
{
[shakeView becomeFirstResponder];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[shakeView resignFirstResponder];
[super viewWillDisappear:animated];
}
Не забывайте, что если у вас есть другие представления, которые становятся первыми респондентами от действий пользователя (например, панель поиска или поле ввода текста), вам также необходимо восстановить статус первого респондента дрожащего представления, когда другой вид уходит в отставку!
Этот метод работает, даже если для applicationSupportsShakeToEdit задано значение NO.
viewDidAppear
вместоviewWillAppear
. Я не уверен почему; может быть, вид должен быть видимым, прежде чем он сможет делать все, что он делает, чтобы начать получать события встряхивания?motionEnded
до того, как встряска фактически прекратилась. Таким образом, используя этот подход, вы получаете несвязанную серию коротких встряхиваний вместо одной длинной. Другой ответ работает намного лучше в этом случае.[super respondsToSelector:
не будет делать то, что вы хотите, так как это эквивалентно вызову,[self respondsToSelector:
который вернетсяYES
. Что тебе нужно[[ShakingView superclass] instancesRespondToSelector:
?Из моего приложения Diceshaker :
Гистерезис предотвращает многократное срабатывание события встряхивания, пока пользователь не остановит встряхивание.
источник
motionBegan
иmotionEnded
события не очень точны или точны с точки зрения определения точного начала и конца дрожания. Такой подход позволяет вам быть настолько точным, насколько вы хотите.Я наконец заставил его работать, используя примеры кода из этого руководства Undo / Redo Manager .
Это именно то, что вам нужно сделать:
источник
applicationSupportsShakeToEdit
-YES
.[self resignFirstResponder];
раньше[super viewWillDisappear:animated];
? Это кажется странным.Во-первых, ответ Кендалла 10 июля - точный.
Теперь ... я хотел сделать что-то подобное (в iPhone OS 3.0+), только в моем случае я хотел, чтобы это было в масштабе всего приложения, чтобы я мог предупреждать различные части приложения, когда происходит сотрясение. Вот что я в итоге сделал.
Во-первых, я подкласс UIWindow . Это легко peasy. Создайте новый файл класса с интерфейсом, таким как
MotionWindow : UIWindow
(не стесняйтесь выбирать свой, естественно). Добавьте метод, например, так:+ Изменить
@"DeviceShaken"
имя уведомления по вашему выбору. Сохраните файл.Теперь, если вы используете MainWindow.xib (стандартный шаблонный код Xcode), зайдите туда и измените класс вашего объекта Window с UIWindow на MotionWindow или как вы его назвали. Сохраните xib. Если вы настроили UIWindow программно, используйте вместо этого новый класс Window.
Теперь ваше приложение использует специализированный класс UIWindow . Везде, где вы хотите получить информацию о встряхивании, подпишитесь на них уведомления! Как это:
Чтобы удалить себя в качестве наблюдателя:
Я положил мой в viewWillAppear: и viewWillDisappear: контроллеров представления. Убедитесь, что ваш ответ на событие встряхивания знает, «оно уже выполняется» или нет. В противном случае, если устройство дважды встряхнуть подряд, у вас возникнет пробка. Таким образом, вы можете игнорировать другие уведомления, пока вы действительно не ответите на исходное уведомление.
Кроме того: вы можете отключить motionBegan против motionEnded . Тебе решать. В моем случае эффект всегда должен иметь место после того, как устройство находится в состоянии покоя (по сравнению с тем, когда оно начинает дрожать), поэтому я использую motionEnded . Попробуйте оба и посмотрите, какой из них имеет больше смысла ... или обнаружите / сообщите обоим!
Еще одно (любопытное?) Наблюдение: обратите внимание, что в этом коде нет признаков управления первым респондентом. Я только попробовал это с Контроллерами Табличного представления, и все, кажется, работает довольно хорошо вместе! Я не могу поручиться за другие сценарии, хотя.
Kendall, et. al - кто-нибудь может сказать, почему это может быть так для подклассов UIWindow ? Это потому, что окно находится наверху пищевой цепи?
источник
Я наткнулся на этот пост в поисках «потрясающей» реализации. Ответ millenomi хорошо сработал для меня, хотя я искал что-то, что требовало более «дрожащего действия», чтобы сработать. Я заменил на логическое значение int shakeCount. Я также переопределил метод L0AccelerationIsShaking () в Objective-C. Вы можете настроить количество встряхивания, необходимое для настройки количества, добавленного в shakeCount. Я не уверен, что нашел оптимальные значения, но, похоже, пока что работает хорошо. Надеюсь, это поможет кому-то:
PS: я установил интервал обновления на 1/15 секунды.
источник
Вам необходимо проверить акселерометр с помощью акселерометра: didAccelerate: метод, который является частью протокола UIAccelerometerDelegate, и проверить, превышают ли значения пороговое значение для количества движения, необходимого для встряхивания.
В акселерометре есть пример кода: didAccelerate: метод в нижней части AppController.m в примере GLPaint, который доступен на сайте разработчиков iPhone.
источник
В iOS 8.3 (возможно, ранее) с Swift это так же просто, как переопределение методов
motionBegan
илиmotionEnded
в вашем контроллере представления:источник
Это основной код делегата, который вам нужен:
Также установите соответствующий код в интерфейсе. то есть:
@interface MyViewController: UIViewController <UIPickerViewDelegate, UIPickerViewDataSource, UIAccelerometerDelegate>
источник
Посмотрите на пример GLPaint.
http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html
источник
Добавьте следующие методы в файл ViewController.m, он работает правильно
источник
Извините, что опубликовал это как ответ, а не как комментарий, но, как вы можете видеть, я новичок в Stack Overflow, и поэтому я еще недостаточно авторитетен, чтобы оставлять комментарии!
В любом случае, я повторяю @cire, чтобы убедиться, что установил статус первого респондента, когда представление является частью иерархии представлений. Так, например, установка статуса первого респондента в вашем
viewDidLoad
методе контроллеров представления не будет работать. И если вы не уверены, работает ли он,[view becomeFirstResponder]
вы получите логическое значение, которое вы можете проверить.Еще один момент: вы можете использовать контроллер представления для захвата события встряхивания, если не хотите создавать подкласс UIView без необходимости. Я знаю, что это не так уж много хлопот, но все же есть возможность. Просто переместите фрагменты кода , которые Kendall поместить в UIView подкласс в контроллер и отправить
becomeFirstResponder
иresignFirstResponder
сообщенияself
вместо подкласса UIView.источник
Во-первых, я знаю, что это старый пост, но он все еще актуален, и я обнаружил, что два ответа с наибольшим количеством голосов не выявили сотрясение как можно раньше . Вот как это сделать:
В вашем ViewController:
источник
Самое простое решение - получить новое корневое окно для вашего приложения:
Тогда в вашем приложении делегат:
Если вы используете раскадровку, это может быть сложнее, я не знаю точно, какой код вам понадобится в делегате приложения.
источник
@implementation
начиная с Xcode 5.Просто используйте эти три метода, чтобы сделать это
для деталей вы можете проверить полный пример кода там
источник
Версия Swiftease, основанная на самом первом ответе!
источник
Чтобы включить это приложение, я создал категорию в UIWindow:
источник