ios - plus - como saber se o iphone xs é original




Como faço para detectar quando alguém sacode um iPhone? (11)

Eu quero reagir quando alguém sacode o iPhone. Eu particularmente não me importo como eles agitam isto, só que ele foi agitado vigorosamente por uma fração de segundo. Alguém sabe como detectar isso?


A solução mais fácil é derivar uma nova janela raiz para o seu aplicativo:

@implementation OMGWindow : UIWindow

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    if (event.type == UIEventTypeMotion && motion == UIEventSubtypeMotionShake) {
        // via notification or something   
    }
}
@end

Em seguida, no delegado da sua aplicação:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[OMGWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    //…
}

Se você estiver usando um Storyboard, isso pode ser mais complicado, não sei o código que você precisará no delegado do aplicativo com precisão.


Adicione os seguintes métodos no arquivo ViewController.m, está funcionando corretamente

    -(BOOL) canBecomeFirstResponder
    {
         /* Here, We want our view (not viewcontroller) as first responder 
         to receive shake event message  */

         return YES;
    }

    -(void) motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
            if(event.subtype==UIEventSubtypeMotionShake)
            {
                    // Code at shake event

                    UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"Motion" message:@"Phone Vibrate"delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
                    [alert show];
                    [alert release];

                    [self.view setBackgroundColor:[UIColor redColor]];
             }
    }
    - (void)viewDidAppear:(BOOL)animated
    {
             [super viewDidAppear:animated];
             [self becomeFirstResponder];  // View as first responder 
     }


Desculpe postar isso como uma resposta em vez de um comentário, mas como você pode ver, sou novo no e, portanto, ainda não sou respeitável o suficiente para postar comentários!

De qualquer forma eu segundo @cire sobre ter certeza de definir o status do primeiro respondedor uma vez que a visão é parte da hierarquia da visão. Portanto, definir o status do primeiro socorrista em seus controladores de viewDidLoad método viewDidLoad não funcionará, por exemplo. E se você não tiver certeza se está funcionando, [view becomeFirstResponder] retorna um booleano que você pode testar.

Outro ponto: você pode usar um controlador de visualização para capturar o evento de tremulação se não quiser criar uma subclasse de UIView desnecessariamente. Eu sei que não é muito trabalho, mas ainda assim a opção está lá. Basta mover os trechos de código que Kendall colocou na subclasse UIView em seu controlador e enviar as mensagens resignFirstResponder e resignFirstResponder para self vez da subclasse UIView.


Este é o código de delegado básico de que você precisa:

#define kAccelerationThreshold      2.2

#pragma mark -
#pragma mark UIAccelerometerDelegate Methods
    - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration 
    {   
        if (fabsf(acceleration.x) > kAccelerationThreshold || fabsf(acceleration.y) > kAccelerationThreshold || fabsf(acceleration.z) > kAccelerationThreshold) 
            [self myShakeMethodGoesHere];   
    }

Também defina o no código apropriado na interface. ie:

@interface MyViewController: UIViewController <UIPickerViewDelegate, UIPickerViewDataSource, UIAccelerometerDelegate>


Eu finalmente fiz isso funcionar usando exemplos de código deste Tutorial do Undo / Redo Manager .
Isso é exatamente o que você precisa fazer:

  • Defina a propriedade applicationSupportsShakeToEdit no Delegado do aplicativo:
  • 
        - (void)applicationDidFinishLaunching:(UIApplication *)application {
    
            application.applicationSupportsShakeToEdit = YES;
    
            [window addSubview:viewController.view];
            [window makeKeyAndVisible];
    }

  • Adicionar / substituir os métodos canBecomeFirstResponder , viewDidAppear: e viewWillDisappear: em seu View Controller:
  • 
    -(BOOL)canBecomeFirstResponder {
        return YES;
    }
    
    -(void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self becomeFirstResponder];
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [self resignFirstResponder];
        [super viewWillDisappear:animated];
    }

  • Adicione o método motionEnded ao seu View Controller:
  • 
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
        if (motion == UIEventSubtypeMotionShake)
        {
            // your code
        }
    }

    Na versão 3.0, agora há uma maneira mais fácil - conecte-se aos novos eventos de movimento.

    O principal truque é que você precisa ter um UIView (não UIViewController) que você queira que o firstResponder receba as mensagens do evento shake. Aqui está o código que você pode usar em qualquer UIView para agitar eventos:

    @implementation ShakingView
    
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
        if ( event.subtype == UIEventSubtypeMotionShake )
        {
            // Put in code here to handle shake
        }
    
        if ( [super respondsToSelector:@selector(motionEnded:withEvent:)] )
            [super motionEnded:motion withEvent:event];
    }
    
    - (BOOL)canBecomeFirstResponder
    { return YES; }
    
    @end

    Você pode facilmente transformar qualquer UIView (mesmo visualizações do sistema) em uma visualização que pode obter o evento shake simplesmente subclassificando a visualização apenas com esses métodos (e selecionando esse novo tipo em vez do tipo base no IB, ou usando-o ao alocar um Visão).

    No controlador de visualização, você deseja definir essa exibição para se tornar o primeiro socorrista:

    - (void) viewWillAppear:(BOOL)animated
    {
        [shakeView becomeFirstResponder];
        [super viewWillAppear:animated];
    }
    - (void) viewWillDisappear:(BOOL)animated
    {
        [shakeView resignFirstResponder];
        [super viewWillDisappear:animated];
    }

    Não se esqueça de que, se você tiver outras visualizações que se tornam respostas de ações do usuário (como uma barra de pesquisa ou campo de entrada de texto), também precisará restaurar o status do socorrista quando a outra exibição for renunciada!

    Esse método funciona mesmo se você definir applicationSupportsShakeToEdit como NO.


    No iOS 8.3 (talvez antes) com o Swift, é tão simples quanto substituir os métodos motionEnded ou motionEnded no seu controlador de visualização:

    class ViewController: UIViewController {
        override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent) {
            println("started shaking!")
        }
    
        override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent) {
            println("ended shaking!")
        }
    }

    Primeiramente, eu sei que este é um post antigo, mas ainda é relevante, e descobri que as duas respostas mais votadas não detectaram o tremor o mais cedo possível . Isto é como fazer isto:

    1. Vincule o CoreMotion ao seu projeto nas fases de criação do alvo:
    2. No seu ViewController:

      - (BOOL)canBecomeFirstResponder {
          return YES;
      }
      
      - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
      {
          if (motion == UIEventSubtypeMotionShake) {
              // Shake detected.
          }
      }

    Primeiro, a resposta de Kendall no dia 10 de julho está correta.

    Agora ... eu queria fazer algo similar (no iPhone OS 3.0+), só que no meu caso eu queria que ele fosse em todo o aplicativo para que eu pudesse alertar várias partes do aplicativo quando ocorresse um tremido. Aqui está o que acabei fazendo.

    Primeiro, subclasse o UIWindow . Isso é fácil. Crie um novo arquivo de classe com uma interface como MotionWindow : UIWindow (sinta-se à vontade para escolher seu próprio, natch). Adicione um método assim:

    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
        if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake) {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"DeviceShaken" object:self];
        }
    }

    Altere @"DeviceShaken" para o nome da notificação de sua escolha. Salve o arquivo.

    Agora, se você usar um MainWindow.xib (material do template Xcode em estoque), vá para lá e altere a classe do seu objeto Window de UIWindow para MotionWindow ou o que quer que seja que você chamou. Salve o xib. Se você configurar o UIWindow programaticamente, use a nova classe Window lá.

    Agora seu aplicativo está usando a classe UIWindow especializada. Onde quer que você queira saber sobre um shake, inscreva-se para receber notificações! Como isso:

    [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(deviceShaken) name:@"DeviceShaken" object:nil];

    Para se retirar como observador:

    [[NSNotificationCenter defaultCenter] removeObserver:self];

    Eu coloquei o meu em viewWillAppear: e viewWillDisappear: onde Controladores de Visualização estão em causa. Certifique-se de que sua resposta ao evento de shake saiba se já está "em andamento" ou não. Caso contrário, se o dispositivo for sacudido duas vezes em sucessão, você terá um pequeno congestionamento. Dessa forma, você pode ignorar outras notificações até terminar sua resposta à notificação original.

    Além disso: Você pode optar por sair do movimento Iniciar de acordo com o movimento final . Você decide. No meu caso, o efeito sempre precisa ocorrer após o dispositivo estar em repouso (vs. quando ele começa a tremer), então eu uso motionEnded . Experimente os dois e veja qual deles faz mais sentido ... ou detecte / notifique para ambos!

    Mais uma observação (curiosa?): Observe que não há sinal de gerenciamento de resposta inicial neste código. Eu só tentei isso com controladores de visão de tabela até agora e tudo parece funcionar muito bem juntos! Eu não posso garantir outros cenários.

    Kendall, et. al - alguém pode falar por que isso pode ser assim para subclasses de UIWindow ? É porque a janela está no topo da cadeia alimentar?


    Você precisa verificar o acelerômetro via accelerometer: didAccelerate: método que faz parte do protocolo UIAccelerometerDelegate e verificar se os valores ultrapassam um limite para a quantidade de movimento necessária para um shake.

    Há um código de amostra decente no acelerômetro: didAccelerate: method na parte inferior do AppController.m no exemplo do GLPaint que está disponível no site do desenvolvedor do iPhone.







    shake