{"id":2162,"date":"2017-04-22T23:33:44","date_gmt":"2017-04-23T03:33:44","guid":{"rendered":"http:\/\/www.rexfeng.com\/blog\/?p=2162"},"modified":"2017-04-22T23:33:44","modified_gmt":"2017-04-23T03:33:44","slug":"using-coremotion-devicemotion-to-keep-image-level-example-xcode-8-3-swift-3-1","status":"publish","type":"post","link":"https:\/\/www.rexfeng.com\/blog\/2017\/04\/using-coremotion-devicemotion-to-keep-image-level-example-xcode-8-3-swift-3-1\/","title":{"rendered":"Using CoreMotion deviceMotion to keep image level example (Xcode 8.3, Swift 3.1)"},"content":{"rendered":"<p>I&#8217;ve been playing around with CoreMotion since it is frankly so cool. I&#8217;ve followed <a href=\"http:\/\/nshipster.com\/cmdevicemotion\/\">NSHipster&#8217;s\u00a0CMDevice\u200bMotion post<\/a>, but\u00a0I made some changes to use the latest Swift v3.1. Below is sample code for using both the\u00a0gyroscope and accelerometer to keep an\u00a0image level when you rotate\u00a0your phone.<\/p>\n<pre>\/\/\r\n\/\/  ViewController.swift\r\n\/\/\r\n\/\/  Created by Rex on 4\/22\/17.\r\n\/\/\r\n\r\nimport UIKit\r\nimport CoreMotion\r\n\r\nclass ViewController: UIViewController {\r\n\r\n    let interval = 0.01\r\n    let imageFilename = \"bg.jpg\"\r\n    let imageWidth = CGFloat(800)\r\n    let imageHeight = CGFloat(1200)\r\n    \r\n    let manager = CMMotionManager()\r\n    var imageView: UIImageView?\r\n\r\n    override func viewDidLoad() {\r\n        super.viewDidLoad()\r\n\r\n        guard manager.isDeviceMotionAvailable else { return }\r\n        \r\n        setImageView()\r\n        \r\n        manager.deviceMotionUpdateInterval = interval\r\n        let queue = OperationQueue()\r\n        \r\n        manager.startDeviceMotionUpdates(to: queue, withHandler: {(data, error) in\r\n            guard let data = data else { return }\r\n            let gravity = data.gravity\r\n            let rotation = atan2(gravity.x, gravity.y) - .pi\r\n\r\n            OperationQueue.main.addOperation {\r\n                self.imageView?.transform = CGAffineTransform(rotationAngle: CGFloat(rotation))\r\n            }\r\n        })\r\n    }\r\n    \r\n    func setImageView() {\r\n        if let img = UIImage(named: imageFilename) {\r\n            let iv = UIImageView(image: img)\r\n\r\n            \/\/ center the image\r\n            let x = (self.view.frame.width\/2)-(imageWidth\/2)\r\n            let y = (self.view.frame.height\/2)-(imageHeight\/2)\r\n            iv.frame = CGRect(x: x, y: y, width: imageWidth, height: imageHeight)\r\n            \r\n            self.view.addSubview(iv)\r\n            self.imageView = iv\r\n        }\r\n    }\r\n    \r\n}\r\n<\/pre>\n<p>The setup is\u00a0simple. Create a new Single View Application project in Xcode. You&#8217;ll need to add a JPG to the Assets.xcassets folder in the project.\u00a0Replace the Viewcontroller with the code below and make sure to update the image filename, width, and height constants.<\/p>\n<p>The code hopefully is straightforward. We make sure the\u00a0CMMotionManager&#8217;s device motion is available. Then, we add the imageview (as the only UIView element we&#8217;re adding to the screen). We use an\u00a0OperationQueue to process the rotation calculation off the main queue. Then we update the imageview with a transform on the main queue.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been playing around with CoreMotion since it is frankly so cool. I&#8217;ve followed NSHipster&#8217;s\u00a0CMDevice\u200bMotion post, but\u00a0I made some changes to use the latest Swift v3.1. Below is sample code for using both the\u00a0gyroscope and accelerometer to keep an\u00a0image level when you rotate\u00a0your phone. \/\/ \/\/ ViewController.swift \/\/ \/\/ Created by Rex on 4\/22\/17. \/\/ [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1029],"tags":[1319,1321,1320,1318,1322,966,1324,1323,1174,1086],"class_list":["post-2162","post","type-post","status-publish","format-standard","hentry","category-programming","tag-cm","tag-cmmotionmanager","tag-coremotion","tag-devicemotion","tag-gravity","tag-ios","tag-level","tag-rotation","tag-swift","tag-xcode"],"_links":{"self":[{"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/posts\/2162","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/comments?post=2162"}],"version-history":[{"count":4,"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/posts\/2162\/revisions"}],"predecessor-version":[{"id":2166,"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/posts\/2162\/revisions\/2166"}],"wp:attachment":[{"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/media?parent=2162"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/categories?post=2162"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rexfeng.com\/blog\/wp-json\/wp\/v2\/tags?post=2162"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}