Відповіді:
З " Підручника 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)
І ось, як ви це робите на Свіфті (якщо ви зіткнулися з тією ж проблемою, що і я)
Посилання проти 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», який збиває з пантелику. Чому яблуко просто не зробило його перерахунком Свіфта.
@ апономаренко вникає в деталі, моя відповідь - саме для Swifters там.
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
і це добре складено
Простий спосіб зробити це за допомогою аудіопослуг:
#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);
}
}
Важлива примітка: Попередження про майбутнє застарівання.
З прошивкою 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: Ви можете знати, що гра вже закінчиться, якщо користувач має дуже низький рівень HP, або небезпечний монстр знаходиться поруч з ними.
У цьому випадку підготовка 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-тактику. Цей гаптичний зворотний зв'язок м'якший, ніж API AudioToolbox.
Для вашого сценарію GAME OVER слід підходити з високим ступенем зворотного зв’язку з інтерфейсом.
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.