Заставить iPhone вибрировать
Как настроить iPhone на вибрацию один раз?
Например, когда игрок теряет жизнь или игра окончена, iPhone должен вибрировать.
11 ответов
Из " Учебника для iPhone: лучший способ проверить возможности устройств iOS":
Есть две, казалось бы, похожие функции, которые принимают параметр kSystemSoundID_Vibrate
:
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Обе функции вибрируют iPhone. Но когда вы используете первую функцию на устройствах, которые не поддерживают вибрацию, она воспроизводит звуковой сигнал. Вторая функция, с другой стороны, ничего не делает на неподдерживаемых устройствах. Поэтому, если вы собираетесь постоянно вибрировать устройство, как говорит здравый смысл, используйте функцию 2.
Сначала добавьте каркас AudioToolbox. AudioToolbox.framework
к вашей цели в фазах сборки.
Затем импортируйте этот заголовочный файл:
#import <AudioToolbox/AudioServices.h>
Swift 3.0
То же, что 2.0, без изменений.
Swift 2.0
AudioToolbox теперь представляет kSystemSoundID_Vibrate
как SystemSoundID
типа, поэтому код:
import AudioToolbox.AudioServices
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)
Вместо того, чтобы идти через дополнительный шаг броска
(Реквизит @Dov)
Оригинальный ответ (Swift 1.x)
И вот как вы делаете это на Swift (на случай, если вы столкнулись с той же проблемой, что и я)
Ссылка против AudioToolbox.framework
(Зайдите в ваш проект, выберите цель, фазы сборки, свяжите бинарный файл с библиотеками, добавьте туда библиотеку)
Как только это будет завершено:
import AudioToolbox.AudioServices
// Use either of these
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
Дрянная вещь в том, что SystemSoundID
в основном typealias
(необычный быстрый typedef
) для UInt32
и kSystemSoundID_Vibrate
регулярный Int
, Компилятор выдает ошибку при попытке привести из Int
в UInt32
, но ошибка читается как "Невозможно преобразовать в SystemSoundID", что сбивает с толку. Почему яблоко просто не сделало его быстрым перечислением вне меня.
@ aponomarenko в деталях, мой ответ только для Swifters там.
Простой способ сделать это с помощью Audio Services:
#import <AudioToolbox/AudioToolbox.h>
...
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
У меня были большие проблемы с этим для устройств, которые каким-то образом отключили вибрацию, но нам нужно было, чтобы она работала независимо, потому что это важно для функционирования нашего приложения, и поскольку это всего лишь целое число для документированного вызова метода, оно пройдет Проверка. Поэтому я попробовал некоторые звуки, которые были за пределами хорошо документированных здесь: https://github.com/TUNER88/iOSSystemSoundsLibrary
Я тогда наткнулся на 1352, который работает независимо от тихого переключателя или настроек на устройстве (Settings->vibrate on ring, vibrate on silent)
,
- (void)vibratePhone;
{
if([[UIDevice currentDevice].model isEqualToString:@"iPhone"])
{
AudioServicesPlaySystemSound (1352); //works ALWAYS as of this post
}
else
{
// Not an iPhone, so doesn't have vibrate
// play the less annoying tick noise or one of your own
AudioServicesPlayAlertSound (1105);
}
}
Важное примечание: предупреждение об устаревании в будущем.
Начиная с iOS 9.0, описание функций API для:
AudioServicesPlaySystemSound(inSystemSoundID: SystemSoundID)
AudioServicesPlayAlertSound(inSystemSoundID: SystemSoundID)
включает в себя следующее примечание:
This function will be deprecated in a future release.
Use AudioServicesPlayAlertSoundWithCompletion or
AudioServicesPlaySystemSoundWithCompletion instead.
Правильный путь будет использовать любой из этих двух:
AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate, nil)
или же
AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate) {
//your callback code when the vibration is done (it may not vibrate in iPod, but this callback will be always called)
}
Запомни
import AVFoundation
Для iPhone 7/7 Plus или новее используйте эти три API-интерфейса обратной связи Haptic.
Доступные API
Для уведомлений:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccured(style: .error)
Доступные стили .error
, .success
, а также .warning
, У каждого есть свое отличительное чувство.
Из документов:
Бетон
UIFeedbackGenerator
подкласс, который создает тактику для сообщения об успехах, неудачах и предупреждениях.
Для простых вибраций:
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccured()
Доступные стили .heavy
, .medium
, а также .light
, Это простые вибрации с различной степенью "твердости".
Из документов:
Бетон
UIFeedbackGenerator
подкласс, который создает тактильные ощущения для имитации физических воздействий
Когда пользователь выбрал предмет
let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()
Это наименее заметный из всех тактильных ощущений, и поэтому он наиболее подходит для случаев, когда тактильные ощущения не должны воспринимать опыт приложения.
Из документов:
Бетон
UIFeedbackGenerator
подкласс, который создает тактильные ощущения, чтобы указать изменение в выборе.
Заметки
Есть несколько вещей, которые стоит запомнить при использовании этих API.
Примечание А
Вы на самом деле не создаете тактильную. Вы запрашиваете систему генерировать тактильный. Система примет решение на основе ниже:
- Если на устройстве возможны тактильные ощущения (есть ли в данном случае устройство Taptic Engine)
- Может ли приложение записывать звук (тактильные сигналы не генерируются во время записи, чтобы предотвратить нежелательные помехи)
- Включены ли тактильные параметры в настройках системы.
Поэтому система будет молчаливо игнорировать ваш запрос о тактильном, если это невозможно. Если это связано с неподдерживаемым устройством, вы можете попробовать это:
func haptic() {
// Get whether the device can generate haptics or not
// If feedbackSupportLevel is nil, will assign 0
let feedbackSupportLevel = UIDevice.current.value(forKey: "_feedbackSupportLevel") as? Int ?? 0
switch feedbackSupportLevel {
case 2:
// 2 means the device has a Taptic Engine
// Put Taptic Engine code here, using the APIs explained above
case 1:
// 1 means no Taptic Engine, but will support AudioToolbox
// AudioToolbox code from the myriad of other answers!
default: // 0
// No haptic support
// Do something else, like a beeping noise or LED flash instead of haptics
}
Заменить комментарии в switch
-case
заявления, и этот тактильный код генерации будет переносимым на другие устройства iOS. Это создаст самый высокий уровень тактильной возможной.
Примечание Б
- Из-за того, что генерация тактильных файлов является задачей аппаратного уровня, может возникнуть задержка между вызовом кода генерации тактового кода и его фактическим выполнением. По этой причине все API-интерфейсы Taptic Engine имеют
prepare()
метод, чтобы привести его в состояние готовности. Используя пример Game Over: вы можете знать, что игра заканчивается, потому что у пользователя очень низкий уровень здоровья или рядом с ними опасный монстр. - Если вы не генерируете тактильный сигнал в течение нескольких секунд, Taptic Engine вернется в состояние ожидания (для экономии заряда аккумулятора)
В этом случае подготовка Taptic Engine создаст более качественный и более отзывчивый опыт.
Например, допустим, ваше приложение использует распознаватель панорамирования для изменения видимой части мира. Вы хотите, чтобы тактильный генератор генерировался, когда пользователь "смотрит" вокруг 360 градусов. Вот как вы могли бы использовать prepare()
:
@IBAction func userChangedViewablePortionOfWorld(_ gesture: UIPanGestureRecogniser!) {
haptic = UIImpactFeedbackGenerator(style: .heavy)
switch gesture.state {
case .began:
// The user started dragging the screen.
haptic.prepare()
case .changed:
// The user trying to 'look' in another direction
// Code to change viewable portion of the virtual world
if virtualWorldViewpointDegreeMiddle = 360.0 {
haptic.impactOccured()
}
default:
break
}
В iOS 10 и на новых iPhone можно также использовать тактильный API. Эта тактильная обратная связь мягче, чем AudioToolbox API.
Для вашего сценария GAME OVER должна подойти сильная обратная связь.
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
Вы можете использовать другие тактильные стили обратной связи.
И если вы используете платформу Xamarin (monotouch), просто позвоните
SystemSound.Vibrate.PlayAlertSound()
В своих путешествиях я обнаружил, что если вы попытаетесь выполнить одно из следующих действий во время записи звука, устройство не будет вибрировать, даже если оно включено.
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Мой метод был вызван в определенное время при измерении движений устройств. Я должен был остановить запись, а затем перезапустить ее после того, как произошла вибрация.
Это выглядело так.
-(void)vibrate {
[recorder stop];
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
[recorder start];
}
recorder
это экземпляр AVRecorder
Надеюсь, что это помогает другим, у которых раньше была такая же проблема.
В Свифте:
import AVFoundation
...
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
В моем случае я использовал AVCaptureSession. AudioToolbox находился на стадии сборки проекта и был импортирован, но все еще не работал. Чтобы заставить его работать, я остановил сеанс до вибрации и продолжил после этого.
#import <AudioToolbox/AudioToolbox.h>
...
@property (nonatomic) AVCaptureSession *session;
...
- (void)vibratePhone;
{
[self.session stopRunning];
NSLog(@"vibratePhone %@",@"here");
if([[UIDevice currentDevice].model isEqualToString:@"iPhone"])
{
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
}
else
{
AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);
}
[self.session startRunning];
}
Все устройства имеют встроенный мотор для создания вибрационных эффектов, а если вам нужна просто быстрая вибрация.
extension UIDevice {
static func vibrate() {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
}
}
Теперь вы можете просто позвонить по мере необходимости.
UIDevice.vibrate()
Ты можешь использовать
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
для iPhone и нескольких новых iPod.
2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
для iPad.