Swift 3 设备运动重力
Swift 3 device motion gravity
我有一个 iPhone 应用程序,其中的关卡基于对 motionmanager 的设备运动调用的 gravityY 参数。我已将水平仪固定为 phone 的俯仰,因为我希望向用户展示 phone 相对于通过其 x 轴的平面(与地面平齐)是升高还是降低...并排或旋转不相关。为此,我对应用程序进行了编程,使其沿着水平(条)滑动指示器(超出水平时为红色)……它的最大行程是水平的每一端。
级别非常好...并显示正确的值,直到用户锁定 phone 并将其放入他或她的后口袋。在此阶段,水平指示器移动到水平的一端(口袋中升高的 phone 的末端),当 phone 被拉出并解锁时,应用程序会不立即恢复水平 - 它仍然不在水平范围内,即使我进行手动函数调用以恢复水平。大约 5 分钟后,电平似乎自行恢复。
代码如下:
func getElevation () {
//now get the device orientation - want the gravity value
if self.motionManager.isDeviceMotionAvailable {
self.motionManager.deviceMotionUpdateInterval = 0.05
self.motionManager.startDeviceMotionUpdates(
to: OperationQueue.current!, withHandler: {
deviceMotion, error -> Void in
var gravityValueY:Double = 0
if(error == nil) {
let gravityData = self.motionManager.deviceMotion
let gravityValueYRad = (gravityData!.gravity.y)
gravityValueY = round(180/(.pi) * (gravityValueYRad))
self.Angle.text = "\(String(round(gravityValueY)))"
}
else {
//handle the error
self.Angle.text = "0"
gravityValueY = 0
}
var elevationY = gravityValueY
//limit movement of bubble
if elevationY > 45 {
elevationY = 45
}
else if elevationY < -45 {
elevationY = -45
}
let outofLevel: UIImage? = #imageLiteral(resourceName: "levelBubble-1")
let alignLevel: UIImage? = #imageLiteral(resourceName: "levelBubbleGR-1")
let highElevation:Double = 1.75
let lowElevation:Double = -1.75
if highElevation < elevationY {
self.bubble.image = outofLevel
}
else if elevationY < lowElevation {
self.bubble.image = outofLevel
}
else {
self.bubble.image = alignLevel
}
// Move the bubble on the level
if let bubble = self.bubble {
UIView.animate(withDuration: 1.5, animations: { () -> Void in
bubble.transform = CGAffineTransform(translationX: 0, y: CGFloat(elevationY))
})
}
})
}
}
我希望关卡几乎立即恢复(2-3 秒内)。我无法强制校准或更新。这是我的第一个 post...帮助感谢。
编辑 - 我尝试使用以下代码设置一个没有任何动画的单独应用程序:
//
import UIKit
import CoreMotion
class ViewController: UIViewController {
let motionManager = CMMotionManager()
@IBOutlet weak var angle: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func startLevel(_ sender: Any) {
startLevel()
}
func startLevel() {
//now get the device orientation - want the gravity value
if self.motionManager.isDeviceMotionAvailable {
self.motionManager.deviceMotionUpdateInterval = 0.1
self.motionManager.startDeviceMotionUpdates(
to: OperationQueue.current!, withHandler: {
deviceMotion, error -> Void in
var gravityValueY:Double = 0
if(error == nil) {
let gravityData = self.motionManager.deviceMotion
let gravityValueYRad = (gravityData!.gravity.y)
gravityValueY = round(180/(.pi) * (gravityValueYRad))
}
else {
//handle the error
gravityValueY = 0
}
self.angle.text = "(\(gravityValueY))"
})}
}
}
仍然以完全相同的方式运行....
好的....所以我通过反复试验弄明白了这一点。首先,我构建了一个 stopGravity 函数,如下所示:
func stopGravity () {
if self.motionManager.isDeviceMotionAvailable {
self.motionManager.stopDeviceMotionUpdates()
}
}
我发现如果调用该函数,级别总是设置正确,例如通过移动到新视图,然后在返回原始视图时重新启动更新。当锁定设备或单击主页按钮时,我需要调用相同的函数,然后在重新加载或返回视图时重新启动重力功能。
为此,我在 viewDidLoad() 中插入了以下内容...
NotificationCenter.default.addObserver(self, selector: #selector(stopGravity), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(stopGravity), name: NSNotification.Name.UIApplicationWillTerminate, object: nil)
这会通知 AppDelegate 并运行函数。这立即解决了问题。
我有一个 iPhone 应用程序,其中的关卡基于对 motionmanager 的设备运动调用的 gravityY 参数。我已将水平仪固定为 phone 的俯仰,因为我希望向用户展示 phone 相对于通过其 x 轴的平面(与地面平齐)是升高还是降低...并排或旋转不相关。为此,我对应用程序进行了编程,使其沿着水平(条)滑动指示器(超出水平时为红色)……它的最大行程是水平的每一端。
级别非常好...并显示正确的值,直到用户锁定 phone 并将其放入他或她的后口袋。在此阶段,水平指示器移动到水平的一端(口袋中升高的 phone 的末端),当 phone 被拉出并解锁时,应用程序会不立即恢复水平 - 它仍然不在水平范围内,即使我进行手动函数调用以恢复水平。大约 5 分钟后,电平似乎自行恢复。
代码如下:
func getElevation () {
//now get the device orientation - want the gravity value
if self.motionManager.isDeviceMotionAvailable {
self.motionManager.deviceMotionUpdateInterval = 0.05
self.motionManager.startDeviceMotionUpdates(
to: OperationQueue.current!, withHandler: {
deviceMotion, error -> Void in
var gravityValueY:Double = 0
if(error == nil) {
let gravityData = self.motionManager.deviceMotion
let gravityValueYRad = (gravityData!.gravity.y)
gravityValueY = round(180/(.pi) * (gravityValueYRad))
self.Angle.text = "\(String(round(gravityValueY)))"
}
else {
//handle the error
self.Angle.text = "0"
gravityValueY = 0
}
var elevationY = gravityValueY
//limit movement of bubble
if elevationY > 45 {
elevationY = 45
}
else if elevationY < -45 {
elevationY = -45
}
let outofLevel: UIImage? = #imageLiteral(resourceName: "levelBubble-1")
let alignLevel: UIImage? = #imageLiteral(resourceName: "levelBubbleGR-1")
let highElevation:Double = 1.75
let lowElevation:Double = -1.75
if highElevation < elevationY {
self.bubble.image = outofLevel
}
else if elevationY < lowElevation {
self.bubble.image = outofLevel
}
else {
self.bubble.image = alignLevel
}
// Move the bubble on the level
if let bubble = self.bubble {
UIView.animate(withDuration: 1.5, animations: { () -> Void in
bubble.transform = CGAffineTransform(translationX: 0, y: CGFloat(elevationY))
})
}
})
}
}
我希望关卡几乎立即恢复(2-3 秒内)。我无法强制校准或更新。这是我的第一个 post...帮助感谢。
编辑 - 我尝试使用以下代码设置一个没有任何动画的单独应用程序:
//
import UIKit
import CoreMotion
class ViewController: UIViewController {
let motionManager = CMMotionManager()
@IBOutlet weak var angle: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func startLevel(_ sender: Any) {
startLevel()
}
func startLevel() {
//now get the device orientation - want the gravity value
if self.motionManager.isDeviceMotionAvailable {
self.motionManager.deviceMotionUpdateInterval = 0.1
self.motionManager.startDeviceMotionUpdates(
to: OperationQueue.current!, withHandler: {
deviceMotion, error -> Void in
var gravityValueY:Double = 0
if(error == nil) {
let gravityData = self.motionManager.deviceMotion
let gravityValueYRad = (gravityData!.gravity.y)
gravityValueY = round(180/(.pi) * (gravityValueYRad))
}
else {
//handle the error
gravityValueY = 0
}
self.angle.text = "(\(gravityValueY))"
})}
}
}
仍然以完全相同的方式运行....
好的....所以我通过反复试验弄明白了这一点。首先,我构建了一个 stopGravity 函数,如下所示:
func stopGravity () {
if self.motionManager.isDeviceMotionAvailable {
self.motionManager.stopDeviceMotionUpdates()
}
}
我发现如果调用该函数,级别总是设置正确,例如通过移动到新视图,然后在返回原始视图时重新启动更新。当锁定设备或单击主页按钮时,我需要调用相同的函数,然后在重新加载或返回视图时重新启动重力功能。
为此,我在 viewDidLoad() 中插入了以下内容...
NotificationCenter.default.addObserver(self, selector: #selector(stopGravity), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(stopGravity), name: NSNotification.Name.UIApplicationWillTerminate, object: nil)
这会通知 AppDelegate 并运行函数。这立即解决了问题。