Unexpected motion effect oscillations in tvOS

I am experiencing motion effect oscillations using the following code

import UIKit  

@UIApplicationMain  
class AppDelegate: UIResponder, UIApplicationDelegate {  
    var window: UIWindow?  

    func application(application: UIApplication,  
                     didFinishLaunchingWithOptions launchOptions: 
                                               [NSObject: AnyObject]?) -> Bool {  
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)  
        self.window!.rootViewController = ExampleController()  
        self.window!.makeKeyAndVisible()  
        return true  
    }  
}  
class ExampleController: UIViewController {  
    override func viewDidLoad() {  
        super.viewDidLoad()  

        let redView = UIView(frame: CGRect(x: 200, y: 200, 
                                           width: 800, height: 500))  
        redView.backgroundColor = UIColor.redColor().colorWithAlphaComponent(0.5)  
        self.view.addSubview(redView)  

        let effect = UIInterpolatingMotionEffect(keyPath: "center.x", 
                                                 type: .TiltAlongHorizontalAxis)  
        effect.minimumRelativeValue = -100  
        effect.maximumRelativeValue = 100  

        let effectGroup = UIMotionEffectGroup()  
        effectGroup.motionEffects = [effect]  

        redView.motionEffects = [effectGroup]  
    }
}

resulting in the following behavior both in Simulator and on the new Apple TV

  • How to cache images only in disk using Kingfisher?
  • Adjust View for keyboard appears when switching UITextField (Swift)
  • What exactly is init coder aDecoder?
  • How to add nil value to Swift Dictionary?
  • Why do I get an error just because I have a large array in Swift?
  • How can I export DAE files for use in Scene Kit without seeing “untitled-animations”?
  • Is there a way to avoid the oscillations?

    2 Solutions Collect From Internet About “Unexpected motion effect oscillations in tvOS”

    I have tried your code in the simulator, printing the horizontal offset:

    public class MyMotionEffect : UIInterpolatingMotionEffect {
        public override func keyPathsAndRelativeValuesForViewerOffset(viewerOffset: UIOffset) -> [String : AnyObject]? {
            print("\(viewerOffset.horizontal)")
    
            return super.keyPathsAndRelativeValuesForViewerOffset(viewerOffset);
        }
    }
    

    After a while I could reproduce the oscillation. The resulting (horizontal) offset has the following chart:

    enter image description here

    You can see the oscillation is already present in the tilt. It seems the device is generating two tilts at once.

    One solution is to add heuristics (compare offset value with two previous and ignore if there was a sign change, or ignore offsets with abrupt change. Neither solution is perfect unfortunately).
    The best solution would probably be to use Core Motion directly and avoid the native transformations entirely. Or use it with smaller distances because then the oscillation won’t be visible.

    I tried your code too. This is not a problem about the simulator.
    The problem comes only when you change the touch direction too fast.
    The UIInterpolatingMotionEffect starts a new motion before finishing to interpolate the previous one.
    So there happen to be two motions acting on your view concurrently.