Respostas:
Do " Tutorial do iPhone: melhor maneira de verificar os recursos dos dispositivos iOS ":
Existem duas funções aparentemente semelhantes que usam um parâmetro kSystemSoundID_Vibrate:
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Ambas as funções vibram o iPhone. Porém, quando você usa a primeira função em dispositivos que não suportam vibração, ele emite um sinal sonoro. A segunda função, por outro lado, não faz nada em dispositivos não suportados. Portanto, se você vibrar o dispositivo continuamente, como alerta, o senso comum diz, use a função 2.
Primeiro, adicione a estrutura AudioToolbox AudioToolbox.framework ao seu destino em Fases de construção.
Em seguida, importe este arquivo de cabeçalho:
#import <AudioToolbox/AudioServices.h>
AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))(pelo menos a partir da versão beta 2)
AudioToolbox agora apresenta a kSystemSoundID_Vibratecomo um SystemSoundIDtipo, de modo que o código é:
import AudioToolbox.AudioServices
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)
Em vez de ter que passar pela etapa de elenco extra
(Adereços para @Dov)
E aqui está como você faz isso no Swift (caso você tenha o mesmo problema que eu)
Link contra AudioToolbox.framework(Vá para o seu projeto, selecione seu destino, crie fases, Vincule o Binário às Bibliotecas, adicione a biblioteca)
Depois de concluído:
import AudioToolbox.AudioServices
// Use either of these
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
A coisa brega é que SystemSoundIDé basicamente um typealias(fantasia rápida typedef) para um UInt32, e o kSystemSoundID_Vibrateé um regular Int. O compilador fornece um erro ao tentar converter de IntparaUInt32 , mas o erro é exibido como "Não é possível converter para SystemSoundID", o que é confuso. Por que a maçã não a transformou em um enum Swift está além de mim.
@ aponomarenko entra em detalhes, minha resposta é apenas para os Swifters por aí.
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)e compilado bem
Uma maneira simples de fazer isso é com os Serviços de áudio:
#import <AudioToolbox/AudioToolbox.h>
...
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Eu tive um grande problema com isso para dispositivos que tinham a vibração desativada de alguma maneira, mas precisávamos que funcionasse independentemente, porque é fundamental para o funcionamento do aplicativo e, como é apenas um número inteiro para uma chamada de método documentada, ele passará validação. Então, eu tentei alguns sons que estavam fora dos bem documentados aqui: TUNER88 / iOSSystemSoundsLibrary
Tropecei em 1352, que está funcionando independentemente da opção silenciosa ou das configurações do dispositivo (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);
}
}
Nota importante: Alerta de descontinuação futura.
No iOS 9.0 , a API funciona com a descrição de:
AudioServicesPlaySystemSound(inSystemSoundID: SystemSoundID)
AudioServicesPlayAlertSound(inSystemSoundID: SystemSoundID)
inclui a seguinte nota:
This function will be deprecated in a future release.
Use AudioServicesPlayAlertSoundWithCompletion or
AudioServicesPlaySystemSoundWithCompletion instead.
O caminho certo a seguir será usar qualquer um destes dois:
AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate, nil)
ou
AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate) {
//your callback code when the vibration is done (it may not vibrate in iPod, but this callback will be always called)
}
lembrar de
import AVFoundation
Para um iPhone 7/7 Plus ou mais recente, use essas três APIs de feedback tátil.
let generator = UINotificationFeedbackGenerator()
generator.notificationOccured(style: .error)
Estilos disponíveis são .error, .successe .warning. Cada um tem sua própria sensação distinta.
Dos documentos :
Uma
UIFeedbackGeneratorsubclasse concreta que cria hápticos para comunicar sucessos, falhas e avisos.
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccured()
Estilos disponíveis são .heavy, .mediume .light. São vibrações simples com graus variados de "dureza".
Dos documentos :
Uma
UIFeedbackGeneratorsubclasse de concreto que cria hápticos para simular impactos físicos
let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()
Esse é o menos perceptível de todos os hápticos e, portanto, é o mais adequado para quando os hápticos não devem assumir a experiência do aplicativo.
Dos documentos :
Uma
UIFeedbackGeneratorsubclasse concreta que cria hápticos para indicar uma mudança na seleção.
Vale lembrar algumas coisas ao usar essas APIs.
Na verdade, você não cria o háptico. Você solicita que o sistema gere um haptic. O sistema decidirá com base no abaixo:
Portanto, o sistema ignorará silenciosamente sua solicitação de um háptico, se não for possível. Se isso ocorre devido a um dispositivo não suportado, você pode tentar o seguinte:
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
}
Substitua os comentários no switch-case instruções e esse código de geração tátil será portátil para outros dispositivos iOS. Gerará o nível mais alto possível de háptico.
prepare() método, para colocá-lo em um estado de prontidão. Usando o exemplo de Game Over: você pode saber que o jogo está prestes a terminar, porque o usuário tem um HP muito baixo ou um monstro perigoso está perto deles.
Nesse caso, a preparação do Taptic Engine criaria uma experiência mais responsiva e de maior qualidade.
Por exemplo, digamos que seu aplicativo use um reconhecedor de gestos de panorâmica para alterar a parte do mundo visível. Você deseja gerar um háptico quando o usuário "olhar" em torno de 360 graus. Aqui está como você pode usar 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!
hapticdentro deste método. Você não está chamando impactOccuredna mesma instância que chama prepare.
Nas minhas viagens, descobri que, se você tentar qualquer um dos seguintes itens enquanto estiver gravando áudio, o dispositivo não vibrará, mesmo se estiver ativado.
1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Meu método foi chamado em um momento específico na medição dos movimentos do dispositivo. Eu tive que parar a gravação e depois reiniciá-la após a vibração.
Parecia assim.
-(void)vibrate {
[recorder stop];
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
[recorder start];
}
recorder é uma instância do AVRecorder.
Espero que isso ajude outras pessoas que tiveram o mesmo problema antes.
No iOS 10 e em iPhones mais novos, você também pode usar a API háptica. Esse feedback tátil é mais suave que a API AudioToolbox.
Para o seu cenário GAME OVER, um feedback de impacto na interface do usuário pesado deve ser adequado.
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
Você pode usar os outros estilos de feedback tátil .
No meu caso, eu estava usando o AVCaptureSession. O AudioToolbox estava nas fases de construção do projeto e foi importado, mas ainda não funcionou. Para fazer funcionar, parei a sessão antes da vibração e continuei depois.
#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];
}
Você pode usar
1) AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);
para iPhone e alguns iPods mais novos.
2) AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
para iPads.