문제

누군가 아이폰을 흔들면 반응하고 싶다. 나는 그들이 어떻게 흔들리는지를 특히 신경 쓰지 않고, 단지 잠깐 동안 격렬하게 손을 흔들 었다는 것을 신경 쓰지 않습니다. 이것을 감지하는 방법을 아는 사람이 있습니까?

도움이 되었습니까?

해결책

3.0에는 이제 더 쉬운 방법이 있습니다. 새로운 모션 이벤트에 연결하십시오.

주요 요령은 Shake Event 메시지를 받기 위해 FIRSTROSPENTER로 원하는 UIVIEW (UIViewController가 아님)가 있어야한다는 것입니다. 다음은 Uiview에서 사용할 수있는 코드가 Shake 이벤트를 얻습니다.

@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

UIVIEW (심지어 시스템보기)를 쉽게 변환 할 수 있으며 이러한 방법으로 만 뷰를 서브 클래징 (IB의 기본 유형 대신이 새로운 유형을 선택하거나 A 할당 할 때 사용하는 새로운 유형을 선택하면 Shake 이벤트를 얻을 수있는보기로 쉽게 변환 할 수 있습니다. 보다).

View Controller 에서이 뷰를 첫 번째 응답자가되도록 설정하려고합니다.

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

사용자 조치에서 첫 번째 응답자가되는 다른 뷰 (검색 창 또는 텍스트 입력 필드와 같은)가있는 경우 다른 뷰가 사임 할 때 흔들리는보기 첫 번째 응답자 상태를 복원해야한다는 것을 잊지 마십시오!

이 메소드는 ApplicationSupportsShaketoEdit를 NO로 설정하더라도 작동합니다.

다른 팁

DICESHAKER 신청:

// Ensures the shake is strong enough on at least two axes before declaring it a shake.
// "Strong enough" means "greater than a client-supplied threshold" in G's.
static BOOL L0AccelerationIsShaking(UIAcceleration* last, UIAcceleration* current, double threshold) {
    double
        deltaX = fabs(last.x - current.x),
        deltaY = fabs(last.y - current.y),
        deltaZ = fabs(last.z - current.z);

    return
        (deltaX > threshold && deltaY > threshold) ||
        (deltaX > threshold && deltaZ > threshold) ||
        (deltaY > threshold && deltaZ > threshold);
}

@interface L0AppDelegate : NSObject <UIApplicationDelegate> {
    BOOL histeresisExcited;
    UIAcceleration* lastAcceleration;
}

@property(retain) UIAcceleration* lastAcceleration;

@end

@implementation L0AppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    [UIAccelerometer sharedAccelerometer].delegate = self;
}

- (void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {

    if (self.lastAcceleration) {
        if (!histeresisExcited && L0AccelerationIsShaking(self.lastAcceleration, acceleration, 0.7)) {
            histeresisExcited = YES;

            /* SHAKE DETECTED. DO HERE WHAT YOU WANT. */

        } else if (histeresisExcited && !L0AccelerationIsShaking(self.lastAcceleration, acceleration, 0.2)) {
            histeresisExcited = NO;
        }
    }

    self.lastAcceleration = acceleration;
}

// and proper @synthesize and -dealloc boilerplate code

@end

histeresis는 사용자가 쉐이크를 멈출 때까지 쉐이크 이벤트가 여러 번 트리거되는 것을 방지합니다.

나는 마침내 이것의 코드 예제를 사용하여 작동하게했다. UNDO/REDO Manager 튜토리얼.
이것이 바로 당신이해야 할 일입니다.

  • 설정 ApplicationSupportsshaketoedit 앱 대의원의 속성 :
  • 
        - (void)applicationDidFinishLaunching:(UIApplication *)application {
    
            application.applicationSupportsShakeToEdit = YES;
    
            [window addSubview:viewController.view];
            [window makeKeyAndVisible];
    }
    

  • 추가/재정의 canbecomefirstresponder, ViewDidAppear : 그리고 ViewWillDisAppear : 뷰 컨트롤러의 메소드 :
  • 
    -(BOOL)canBecomeFirstResponder {
        return YES;
    }
    
    -(void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self becomeFirstResponder];
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [self resignFirstResponder];
        [super viewWillDisappear:animated];
    }
    

  • 추가 동의했다 뷰 컨트롤러에 대한 메소드 :
  • 
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
        if (motion == UIEventSubtypeMotionShake)
        {
            // your code
        }
    }
    

    첫째, Kendall의 7 월 10 일 답변은 Spot-on입니다.

    이제 ... 비슷한 일을하고 싶었습니다 (iPhone OS 3.0+에서). 제 경우에만 앱 전체를 원했기 때문에 경고 할 수있었습니다. 여러 쉐이크가 발생했을 때 앱의 일부. 여기 내가 한 일이 있습니다.

    먼저, 나는 하위 클래식했다 uiwindow. 이것은 쉽게 심하게입니다. 다음과 같은 인터페이스로 새 클래스 파일을 만듭니다. MotionWindow : UIWindow (자신의 나치를 자유롭게 선택하십시오). 그러한 방법을 추가하십시오.

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

    변화 @"DeviceShaken" 선택한 알림 이름으로. 파일을 저장하십시오.

    이제 mainWindow.xib (스톡 Xcode 템플릿 물건)를 사용하는 경우 거기에 들어가서 창 객체의 클래스를 uiwindow 에게 Motionwindow 또는 당신이 그것을 부르는 것. XIB를 저장하십시오. 설정 한 경우 uiwindow 프로그래밍 방식으로, 대신 새 윈도우 클래스를 사용하십시오.

    이제 앱이 전문화 된 것을 사용하고 있습니다 uiwindow 수업. 쉐이크에 대해 이야기하고 싶은 곳마다 알림에 가입하십시오! 이와 같이:

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

    관찰자로서 자신을 제거하려면 :

    [[NSNotificationCenter defaultCenter] removeObserver:self];
    

    나는 내 것을 넣었다 ViewWillAppear : 그리고 ViewWillDisAppear : 보기 컨트롤러가 관련된 곳. Shake 이벤트에 대한 응답이 "이미 진행중인"인지 아닌지 알고 있는지 확인하십시오. 그렇지 않으면 장치가 연속적으로 두 번 흔들 리면 Li'l Traffic Jam이 있습니다. 이렇게하면 원래 알림에 진정으로 응답 할 때까지 다른 알림을 무시할 수 있습니다.

    또한 : 당신은 큐를 선택할 수 있습니다 MotionBegan vs. 동의했다. 그것은 당신에게 달려 있습니다. 제 경우에는 효과가 항상 발생해야합니다. ~ 후에 장치가 휴식을 취하고 있습니다 (Vs. 흔들기 시작할 때). 동의했다. 둘 다 시도하고 어느 것이 더 의미가 있는지 보거나 ... 둘 다를 감지/알림을 확인하십시오!

    여기에 하나 더 (호기심이 있습니까?) 관찰 :이 코드에는 첫 번째 응답자 관리의 징후가 없습니다. 나는 지금까지 테이블 뷰 컨트롤러로 이것을 시도했으며 모든 것이 함께 잘 작동하는 것 같습니다! 그래도 다른 시나리오를 보증 할 수는 없습니다.

    Kendall, et. AL- 누구든지 이것이 왜 그렇게 할 수 있는지 이야기 할 수 있습니까? uiwindow 서브 클래스? 창문이 먹이 사슬의 상단에 있기 때문입니까?

    나는 "흔들리는"구현을 찾고있는이 게시물을 발견했습니다. Millenomi의 대답은 나에게 잘 작동했지만, 트리거하기 위해 약간 더 "흔들리는 행동"이 필요한 것을 찾고있었습니다. 나는 int shakecount로 부울 가치로 교체했습니다. 또한 Objective-C에서 l0accelerationisshaking () 메소드를 다시 구현했습니다. Shakecount에 추가 된 탄수를 조정하여 필요한 흔들림을 조정할 수 있습니다. 나는 아직 최적의 값을 찾았 음을 확신하지 못하지만 지금까지 잘 작동하는 것 같습니다. 이것이 누군가를 도울 수 있기를 바랍니다.

    - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
        if (self.lastAcceleration) {
            if ([self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.7] && shakeCount >= 9) {
                //Shaking here, DO stuff.
                shakeCount = 0;
            } else if ([self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.7]) {
                shakeCount = shakeCount + 5;
            }else if (![self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.2]) {
                if (shakeCount > 0) {
                    shakeCount--;
                }
            }
        }
        self.lastAcceleration = acceleration;
    }
    
    - (BOOL) AccelerationIsShakingLast:(UIAcceleration *)last current:(UIAcceleration *)current threshold:(double)threshold {
        double
        deltaX = fabs(last.x - current.x),
        deltaY = fabs(last.y - current.y),
        deltaZ = fabs(last.z - current.z);
    
        return
        (deltaX > threshold && deltaY > threshold) ||
        (deltaX > threshold && deltaZ > threshold) ||
        (deltaY > threshold && deltaZ > threshold);
    }
    

    추신 : 업데이트 간격을 1/15 초로 설정했습니다.

    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 15)];
    

    가속도계를 통해 가속도계를 점검해야합니다. didaccelerate : uiaccercelerometerdelegate protocol의 일부인 방법을 확인하고 값이 흔들리는 데 필요한 움직임의 양에 대한 임계 값을 넘어가는지 확인해야합니다.

    가속도계에는 적절한 샘플 코드가 있습니다 : didaccelerate : iPhone 개발자 사이트에서 사용할 수있는 glpaint 예제에서 AppController.m 하단의 메소드.

    Swift와 함께 iOS 8.3 (아마도 이전)에서는 motionBegan 또는 motionEnded 뷰 컨트롤러의 메소드 :

    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!")
        }
    }
    

    이것은 필요한 기본 대의원 코드입니다.

    #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];   
        }
    

    또한 인터페이스에서 적절한 코드로 설정하십시오. 즉:

    @Interface MyViewController : uiviewControlleru003CUIPickerViewDelegate, UIPickerViewDataSource, UIAccelerometerDelegate>

    ViewController.m 파일에 다음 메소드 추가가 올바르게 작동합니다.

        -(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 
         }
    

    댓글이 아닌 답변으로 게시 한 것은 죄송하지만, 알 수 있듯이 나는 오버플로 스택을 처음 접 했으므로 아직 댓글을 게시 할만 큼 평판이 좋지 않습니다!

    어쨌든 나는 뷰가 View 계층 구조의 일부라면 첫 번째 응답자 상태를 설정하는 것에 대해 두 번째 @cire. 따라서 뷰 컨트롤러에서 첫 번째 응답자 상태를 설정합니다 viewDidLoad 예를 들어 메소드는 작동하지 않습니다. 그리고 그것이 작동하는지 확실하지 않은 경우 [view becomeFirstResponder] 테스트 할 수있는 부울을 반환합니다.

    또 다른 요점 : 당신 ~할 수 있다 view 컨트롤러를 사용하여 UIView 서브 클래스를 불필요하게 만들고 싶지 않은 경우 Shake 이벤트를 캡처하십시오. 나는 그것이 그다지 번거롭지는 않지만 여전히 옵션이 있습니다. Kendall이 UIView 하위 클래스에 넣은 코드 스 니펫을 컨트롤러에 넣고 becomeFirstResponder 그리고 resignFirstResponder 메시지 self uiview 서브 클래스 대신.

    우선, 나는 이것이 오래된 게시물이라는 것을 알고 있지만 여전히 관련이 있으며, 가장 높은 투표 된 두 가지 답변은 그렇지 않다는 것을 알았습니다. 최대한 빨리 흔들림을 감지하십시오. 이것은 그것을하는 방법입니다 :

    1. 대상의 빌드 단계에서 프로젝트에 링크를 연결합니다.CoreMotion
    2. ViewController에서 :

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

    가장 쉬운 솔루션은 애플리케이션을위한 새 루트 창을 도출하는 것입니다.

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

    그런 다음 신청서에서 :

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

    스토리 보드를 사용하는 경우 더 까다로울 수 있습니다. 응용 프로그램 대의원에서 필요한 코드를 정확하게 알 수 없습니다.

    이 세 가지 방법을 사용하여 수행하십시오

    - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
    - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{
    

    자세한 내용은 전체 예제 코드를 확인할 수 있습니다. 거기

    첫 번째 답변을 기반으로 한 신속한 버전!

    override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
        if ( event?.subtype == .motionShake )
        {
            print("stop shaking me!")
        }
    }
    

    이 응용 프로그램 전체를 가능하게하기 위해 Uiwindow에서 카테고리를 만들었습니다.

    @implementation UIWindow (Utils)
    
    - (BOOL)canBecomeFirstResponder
    {
        return YES;
    }
    
    - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
        if (motion == UIEventSubtypeMotionShake) {
            // Do whatever you want here...
        }
    }
    
    @end
    
    라이센스 : CC-BY-SA ~와 함께 속성
    제휴하지 않습니다 StackOverflow
    scroll top