How to get motion events with the Apple TV remote

杀马特。学长 韩版系。学妹 提交于 2020-01-12 05:26:10

问题


Has anybody figured out how to get motion events working with the new apple TV remote? Thanks.

I've tried calling

override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?) {
    super.motionBegan(motion, withEvent: event)
    print("motion!")
}
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
    super.motionEnded(motion, withEvent: event)
    print("motion ended!")
}

With and without calling super gives me nothing.


回答1:


A great swift example can be found here: https://forums.developer.apple.com/message/65560#65560 It's basically what Daniel Storm said above, but following this got it working for me. Here's what I did.

In appDelegate:

 var motionDelegate: ReactToMotionEvents? = nil   

     func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {  
        let center = NSNotificationCenter.defaultCenter()  
        center.addObserver(self, selector: "setupControllers:", name: GCControllerDidConnectNotification, object: nil)  
        center.addObserver(self, selector: "setupControllers:", name: GCControllerDidDisconnectNotification, object: nil)  
        GCController.startWirelessControllerDiscoveryWithCompletionHandler { () -> Void in  

        }  
        return true  
    }  

    func setupControllers(notif: NSNotification) {  
        print("controller connection")  
        let controllers = GCController.controllers()  
        for controller in controllers {  
            controller.motion?.valueChangedHandler = { (motion: GCMotion)->() in  
                if let delegate = self.motionDelegate {  
                    delegate.motionUpdate(motion)  
                }  
            }  
        }  
    }  

protocol ReactToMotionEvents {  
    func motionUpdate(motion: GCMotion) -> Void  
}  

Where I want it implemented, in my case an SKScene:

import SpriteKit  
import GameController  
class GameScene: SKScene, ReactToMotionEvents {  

    override func didMoveToView(view: SKView) {   
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate  
        appDelegate.motionDelegate = self  

    }  

    func motionUpdate(motion: GCMotion) {  
        print("x: \(motion.userAcceleration.x)   y: \(motion.userAcceleration.y)")  
    }  
}  



回答2:


Via How to access motion & orientation information of remote:


First of all, one needs to use NSNotificationCenter to find the controllers. Probably best to do this when app launches. Something like this:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerDidConnect:) name:GCControllerDidConnectNotification object:nil];  

We can then use the following code after connecting to store the device info in a property:

- (void)controllerDidConnect:(NSNotification *)notification {  
    self.myController = notification.object;  
}  

The remote profile is a subclass of the micro gamepad profile. Motion and other data can be tracked by adding a value changed event handler:

  GCMicroGamepad *profile =  self.myController.microGamepad  
  profile.valueChangedHandler= ^ (GCMicroGamepad *gamepad, GCControllerElement *element) {  
        if (self.myController.motion) {  
            NSLog(@"motion supported");  
            NSLog(@"gravity: %f %f %f", self.myController.motion.gravity.x, self.myController.motion.gravity.y, self.myController.motion.gravity.z);  
            NSLog(@"userAcc: %f %f %f", self.myController.motion.userAcceleration.x, self.myController.motion.userAcceleration.y, self.myController.motion.userAcceleration.z);  
            NSLog(@"rotationRate: %f %f %f", self.myController.motion.rotationRate.x, self.myController.motion.rotationRate.y, self.myController.motion.rotationRate.z);  
            NSLog(@"attitude: %f %f %f %f", self.myController.motion.attitude.x, self.myController.motion.attitude.y, self.myController.motion.attitude.z, self.myController.motion.attitude.w);  
        }  
    };  




回答3:


Thought I would update CodyMace's great answer with Swift 4.0 syntax

In appDelegate (You will need to import GameController here, too):

var motionDelegate: ReactToMotionEvents? = nil


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    let center = NotificationCenter.default
    center.addObserver(self, selector: #selector(setupControllers), name: NSNotification.Name.GCControllerDidConnect, object: nil)
    center.addObserver(self, selector: #selector(setupControllers), name: NSNotification.Name.GCControllerDidDisconnect, object: nil)
    GCController.startWirelessControllerDiscovery { () -> Void in

    }
    return true
}

@objc func setupControllers(notif: NSNotification) {
    print("controller connection")
    let controllers = GCController.controllers()
    for controller in controllers {
        controller.motion?.valueChangedHandler = { (motion: GCMotion)->() in
            if let delegate = self.motionDelegate {
                delegate.motionUpdate(motion: motion)
            }
        }
    }
}

The protocol stays the same

protocol ReactToMotionEvents {
func motionUpdate(motion: GCMotion) -> Void

}

And where you want implemented

import SpriteKit  
import GameController  
class GameScene: SKScene, ReactToMotionEvents {  

    override func didMoveToView(view: SKView) {   
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.motionDelegate = self

    }  

    func motionUpdate(motion: GCMotion) {  
        print("x: \(motion.userAcceleration.x)   y: \(motion.userAcceleration.y)")  
    }  
}  


来源:https://stackoverflow.com/questions/32832541/how-to-get-motion-events-with-the-apple-tv-remote

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!