Ответы:
Из « Учебника для iPhone: лучший способ проверить возможности устройств iOS »:
Есть две схожие функции, которые принимают параметр kSystemSoundID_Vibrate
:
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Обе функции вибрируют iPhone. Но когда вы используете первую функцию на устройствах, которые не поддерживают вибрацию, она воспроизводит звуковой сигнал. Вторая функция, с другой стороны, ничего не делает на неподдерживаемых устройствах. Поэтому, если вы собираетесь постоянно вибрировать устройство, как говорит здравый смысл, используйте функцию 2.
Во-первых, добавьте платформу AudioToolbox AudioToolbox.framework
к вашей цели на этапах сборки.
Затем импортируйте этот заголовочный файл:
#import <AudioToolbox/AudioServices.h>
AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))
(по крайней мере, в бета-версии 2)
AudioToolbox теперь представлен kSystemSoundID_Vibrate
как SystemSoundID
тип, поэтому код:
import AudioToolbox.AudioServices
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)
Вместо того, чтобы идти через дополнительный шаг броска
(Реквизит @Dov)
И вот как вы делаете это на Swift (на случай, если вы столкнулись с той же проблемой, что и я)
Ссылка на AudioToolbox.framework
(перейдите к своему проекту, выберите цель, этапы сборки, Link Binary with Libraries, добавьте туда библиотеку)
Как только это будет завершено:
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 там.
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
и он прекрасно скомпилирован
Простой способ сделать это с помощью 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
Для 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
подкласс, который создает тактильные ощущения, чтобы указать на изменение в выборе.
Есть несколько вещей, которые стоит помнить при использовании этих 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
}
import UIKit
!
haptic
внутри этого метода. Вы не вызываете impactOccured
тот же экземпляр, который вызываете prepare
.
В своих путешествиях я обнаружил, что если вы попытаетесь выполнить одно из следующих действий во время записи звука, устройство не будет вибрировать, даже если оно включено.
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 должна подойти сильная обратная связь с UI.
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
Вы можете использовать другие тактильные стили обратной связи .
В моем случае я использовал 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];
}
Ты можешь использовать
1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);
для iPhone и нескольких новых iPod.
2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
для iPad.