如何检查是否启用了视差

时间:2013-12-03 20:29:24

标签: ios iphone objective-c

我正在制作壁纸应用,并想检查用户是否在其iOS 7设备上启用了视差。在Objective-C中有没有办法让我检查一下? Apple是否授予我们开发人员检查此布尔值的权限?

即。如果启用了视差,则执行step1否则执行step2

3 个答案:

答案 0 :(得分:12)

从iOS 8开始:

// Returns whether the system preference for reduce motion is enabled
UIKIT_EXTERN BOOL UIAccessibilityIsReduceMotionEnabled() NS_AVAILABLE_IOS(8_0);
UIKIT_EXTERN NSString *const UIAccessibilityReduceMotionStatusDidChangeNotification NS_AVAILABLE_IOS(8_0);

对于早于iOS 8的任何内容,我都不认为这是一种合法的方式。

答案 1 :(得分:5)

根据Gabriele的回答,似乎没有办法直接读取这个值。

作为一种解决方法,你可以利用这样一个事实:UIInterpolatingMotionEffect如果运动是默认值,则会执行某些操作,但如果启用了减少运动则不会执行任何操作。

因此,请使用自定义UIView类,并在应用程序启动时立即附加UIInterpolatingMotionEffect的实例。如果属性已更改,请设置标志。稍后检查那个标志。

可能存在一些您可以依赖的其他经验副作用,但初步认为您的用户会在使用您的应用时移动设备。所以你肯定知道他们是否有动作并且已经移动了他们的设备,否则你将无法知道他们是否关闭了动作或者没有移动他们的设备。

也许更聪明的人能想出更好的东西?

编辑:示例代码。所面临的问题正如评论中所讨论的那样:该属性必须是可动画的,其具有需要手动轮询循环的净效果。在应用程序的某个位置添加此视图的实例,理想情况是在启动时,以便它在应用程序的整个生命周期内保持在屏幕上,当然,视图控制器层次结构允许它。然后观看parallaxHasOccurred属性。符合KVO标准,或者您可以进行投票。如上所述,它可能会产生漏报,但绝不会产生误报。

@interface PTParallaxTestView : UIView

// this key is KVO compliant
@property (nonatomic, assign) BOOL parallaxHasOccurred;

@end


@implementation PTParallaxTestView
{
    CGPoint _basePosition;
    UIMotionEffectGroup *_effectGroup;
}

- (void)didMoveToSuperview
{
    // cancel any detection loop we may have ongoing
    [NSObject cancelPreviousPerformRequestsWithTarget:self];

    // if anything still in doubt and we're on a view then start the
    // detection loop
    if(!self.parallaxHasOccurred && self.superview)
    {
        // add motion effects if they're not already attached; attach both to the centre property
        if(!_effectGroup)
        {
            UIInterpolatingMotionEffect *horizontalMotionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
            horizontalMotionEffect.minimumRelativeValue = @(0);
            horizontalMotionEffect.maximumRelativeValue = @(100);

            UIInterpolatingMotionEffect *verticalMotionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
            verticalMotionEffect.minimumRelativeValue = @(0);
            verticalMotionEffect.maximumRelativeValue = @(100);

            _effectGroup = [[UIMotionEffectGroup alloc] init];
            _effectGroup.motionEffects = @[verticalMotionEffect, horizontalMotionEffect];
            [self addMotionEffect:_effectGroup];
        }

        // kick off inspection in 0.1 seconds; we'll subsequently inspect
        // every 0.5 seconds
        [self performSelector:@selector(beginCheckingPresentationPosition) withObject:nil afterDelay:0.1];
    }
}

- (void)beginCheckingPresentationPosition
{
    // set the base position and do the first check in 0.5 seconds
    _basePosition = [[[self layer] presentationLayer] position];
    [self performSelector:@selector(checkPresentationPosition) withObject:nil afterDelay:0.5];
}

- (void)checkPresentationPosition
{
    // quick note on presentationLayer:
    //
    //  The property supplied to UIInterpolatingMotionEffect must be animatable. So we can't just create our own.
    //  UIKit will then apply effects directly to the layer. Furthermore, the layer itself will act as if in a
    //  perpetual animation so its properties won't directly be affected. We'll have to query the presentationLayer.
    //  (and that's also why we're pulling rather than using KVO or a suitable subclass to push)
    //
    CGPoint newPosition = [[[self layer] presentationLayer] position];

    // if the position has changed since the original test then things are in motion
    if(fabs(newPosition.x - _basePosition.x) > 0.125 || fabs(newPosition.y - _basePosition.y) > 0.125)
        self.parallaxHasOccurred = YES;

    // check again in 0.5 seconds only if we don't already know the answer
    if(!self.parallaxHasOccurred)
        [self performSelector:@selector(checkPresentationPosition) withObject:nil afterDelay:0.5];
}

@end

答案 2 :(得分:1)

对于不支持视差的设备(即iPhone 5之前的任何iPhone型号),您只需check the model并确保没有视差。

对于支持它的设备,您应该以编程方式检查 Reduce Motion 辅助功能设置,但显然没有用于检查该选项是否已启用的公共API。

根据UIKit Function Reference,您可以执行的唯一检查如下

  • UIAccessibilityPostNotification
  • UIAccessibilityIsVoiceOverRunning
  • UIAccessibilityIsClosedCaptioningEnabled
  • UIAccessibilityRequestGuidedAccessSession
  • UIAccessibilityIsGuidedAccessEnabled
  • UIAccessibilityIsInvertColorsEnabled
  • UIAccessibilityIsMonoAudioEnabled
  • UIAccessibilityZoomFocusChanged
  • UIAccessibilityRegisterGestureConflictWithZoom
  • UIAccessibilityConvertFrameToScreenCoordinates
  • UIAccessibilityConvertPathToScreenCoordinates