Как iPhone может быть настроен на вибрацию один раз?
Например, когда игрок теряет жизнь или игра заканчивается, iPhone должен вибрировать.
Как iPhone может быть настроен на вибрацию один раз?
Например, когда игрок теряет жизнь или игра заканчивается, iPhone должен вибрировать.
От " iPhone Tutorial: лучший способ проверить возможности устройств iOS:
Есть две, казалось бы, похожие функции, которые принимают параметр kSystemSoundID_Vibrate
:
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Обе функции вибрируют iPhone. Но, когда вы используете первый на устройствах, которые не поддерживают вибрацию, он воспроизводит звуковой сигнал звук. Вторая функция, с другой стороны, ничего не делает неподдерживаемые устройства. Поэтому, если вы собираетесь вибрировать устройство постоянно, как предупреждение, здравый смысл говорит, используйте функцию 2.
Сначала добавьте фреймворк AudioToolbox AudioToolbox.framework
к вашей цели на этапах сборки.
Затем импортируйте этот файл заголовка:
#import <AudioToolbox/AudioServices.h>
AudioToolbox теперь представляет kSystemSoundID_Vibrate
как тип SystemSoundID
, поэтому код выглядит так:
import AudioToolbox.AudioServices
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)
Вместо того, чтобы идти через дополнительный шаг броска
(Реквизит @Dov)
И вот как вы это делаете на Swift (на случай, если вы столкнулись с той же проблемой, что и я)
Ссылка на AudioToolbox.framework
(AudioToolbox.framework
в свой проект, выберите цель, фазы сборки, AudioToolbox.framework
с библиотеками, добавьте туда библиотеку)
Как только это будет завершено:
import AudioToolbox.AudioServices
// Use either of these
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
SystemSoundID
вещь в том, что SystemSoundID
- это в основном typealias
(fancy swift typedef
) для UInt32
, а kSystemSoundID_Vibrate
- это обычный Int
. Компилятор выдает ошибку при попытке преобразования из Int
в UInt32
, но эта ошибка читается как "Невозможно преобразовать в SystemSoundID", что сбивает с толку. Почему яблоко просто не сделало его быстрым перечислением вне меня.
@aponomarenko углубляется в детали, мой ответ только для Swifters.
Простой способ сделать это с помощью Audio Services:
#import <AudioToolbox/AudioToolbox.h>
...
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
У меня были большие проблемы с этим для устройств, которые каким-то образом отключили вибрацию, но нам нужно было работать независимо, потому что это важно для работы нашего приложения, и поскольку это всего лишь целое число с запросом на документальный метод, он пройдет проверку. Поэтому я пробовал некоторые звуки, которые были за пределами хорошо документированных здесь: 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
И если вы используете инфраструктуру Xamarin (monotouch), просто позвоните
SystemSound.Vibrate.PlayAlertSound()
В моих путешествиях я обнаружил, что если вы пытаетесь выполнить одно из следующих действий при записи звука, устройство не будет вибрировать, даже если оно включено.
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Мой метод вызывался в определенное время при измерении движений устройств. Я должен был остановить запись, а затем перезапустить ее после того, как произошла вибрация.
Это выглядело так.
-(void)vibrate {
[recorder stop];
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
[recorder start];
}
recorder
- это экземпляр AVRecorder.
Надеюсь, что это поможет другим, у которых была такая же проблема.
В iOS 10 и на новых iPhone можно также использовать тактильный API. Эта тактильная обратная связь мягче, чем AudioToolbox API.
Для вашего сценария GAME OVER должна подойти сильная обратная связь.
UIImpactFeedbackGenerator(style:.heavy).impactOccurred()
Вы можете использовать другие тактильные стили обратной связи.
В Swift:
import AVFoundation
...
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
Для iPhone 7/7 Plus или новее используйте эти три API-интерфейса обратной связи Haptic.
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
который создаетUIFeedbackGenerator
, чтобы указать на изменение в выборе.
Есть несколько вещей, которые стоит запомнить при использовании этих API.
Вы на самом деле не создаете тактильную. Вы запрашиваете систему генерировать тактильный. Система примет решение на основе ниже:
Поэтому система будет молчаливо игнорировать ваш запрос о тактильном, если это невозможно. Если это связано с неподдерживаемым устройством, вы можете попробовать это:
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. Это создаст самый высокий уровень тактильной возможной.
prepare()
, чтобы перевести его в состояние готовности. Используя пример Game Over: вы можете знать, что игра заканчивается, потому что у пользователя очень низкий уровень здоровья или рядом с ними опасный монстр.
В этом случае подготовка 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
}
В моем случае я использовал 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()
импортировать AudioToolbox.AudioServices
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate)
Вы можете использовать
1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);
для iPhone и несколько новых iPod.
2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
для iPads.