Swift: get values from Accelerometer and Gyroscope via CMMotionManager

To access data from Accelerometer and Gyroscope we are going to use CMMotionManager.
Here’s the class what wraps everything related to motion API (CMMotionManager).
And here’s the code:
Continue reading “Swift: get values from Accelerometer and Gyroscope via CMMotionManager”

Social Share Toolbar

swift: How to insert animated watermark into the video, or how to merge two videos

So I have a video from camera and array of images – result of screen capturing, basically the list of screenshots.
I want to merge them and add ability for User to save the resulted video on the phone. Let’s insert static image as a watermark as well as animated (video in video) watermark into the main video.

Continue reading “swift: How to insert animated watermark into the video, or how to merge two videos”

Social Share Toolbar

How to add pixel-perfect physics to an SKSpriteNode

To perfect the collision detection, basically to ignore transparency during the interest we can use SKPhysicsBody. The idea here is to have two images – one is what User sees, another is very simplified version for SpriteKit engine – simplified from color and geometry standpoint. The more complex “collision body” is the more resources it will spend during each frame to calculate collisions. Just for instance here’s the actual image and it’s “mask”

Now we are ready for some code
Continue reading “How to add pixel-perfect physics to an SKSpriteNode”

Social Share Toolbar

Swift: How to create iOS Today extension and share data with containing app

Do you happen had a chance to see the 3d touch icon widget or iOS Today Extension, let’s take a look at how to create an Extension in swift, how to open containing app and how to share data with containing app.

To add Today Extension to the project click “file” -> “new” -> “target”: chose “Today Extension”.
Let’s go to “Capabilities” tab and enable “App Groups” for both AppWithExtension and Extension targets, for both app and extension you need to click “+” icon under the “App Groups” and add Groups to you app id, e.g. like here


Continue reading “Swift: How to create iOS Today extension and share data with containing app”

Social Share Toolbar

Swift: how to use 3D Touch – Introduction

3D Touch or force touch – is a new feature that have been introduced in the iPhone 6s. It’s interesting to know that you can get touch force, it is a number from 0 up to 6.6667, actually it a number from 0 up to maximumPossibleForce.

Let’s take a look at how to check if 3d touch is supported on current device:

func is3dTouchAvailable(traitCollection: UITraitCollection) -> Bool {
    return traitCollection.forceTouchCapability == UIForceTouchCapability.available
}
 
// Let's call it somewhere from the GameScene for instance
override func didMove(to view: SKView) {
 
    hardwareService.initDevice()
    if(is3dTouchAvailable(traitCollection: self.view!.traitCollection)) {
       //...
    }
 
}

Feel free to take a look at the example project – I’ll provide the link in the end of this post.
So this is a good practice to check whether 3d touch is supported or not.

Here’s an example of how to get the force of the 3d touch

func touchMoved(touch: UITouch, toPoint pos: CGPoint) {
    let location = touch.location(in: self)
    let node = self.atPoint(location)
 
    //...
    if is3dTouchEnabled {
        bubble.setPressure(pressurePercent: touch.force / touch.maximumPossibleForce)
    } else {
        // It is important to use touchMoved for iPhones w/o 3dTouch,
        // So we can "emulate" it.
        bubble.setPressure(pressurePercent: 1)
    }
}

The current value of the Touch’s force is touch.force and the touch.maximumPossibleForce is a good one to convert force value to the “percentage”.
This code is from the small example of how to “emulate” the bubble reacting on the force of the touch.
https://github.com/DjComandos/3dTouch
To try this on your iPhone 6s/7 you can install this bubble wrap app real quick.

Here is my previous post with more details about Haptic feedback.

Social Share Toolbar

WatchOS 2 tutorial: Activity Ring – WKInterfaceActivityRing

Just a quick example how to use WKInterfaceActivityRing and HKActivitySummary to show Activity Ring.

Simulator Screen Shot Jun 7, 2016, 8.58.27 PM

Go ahead and drag “Activity Ring” on your Interface Controller, use Assistant Editor to add Outlet to your Controller, e.g.

@IBOutlet var activityRing: WKInterfaceActivityRing!

All you need to set up Activity Ring values is to create and initialize HKActivitySummary, here is the sample code (for simplicity we are going to use the same values for all the rings)

let summary = HKActivitySummary()
let value: Double = 2
let goal: Double = 10
 
summary.activeEnergyBurned = HKQuantity(unit: HKUnit.kilocalorieUnit(), doubleValue: value)
summary.activeEnergyBurnedGoal = HKQuantity(unit: HKUnit.kilocalorieUnit(), doubleValue: goal)
 
summary.appleExerciseTime = HKQuantity(unit: HKUnit.minuteUnit(), doubleValue: value)
summary.appleExerciseTimeGoal = HKQuantity(unit: HKUnit.minuteUnit(), doubleValue: goal)
 
summary.appleStandHours = HKQuantity(unit: HKUnit.countUnit(), doubleValue: value)
summary.appleStandHoursGoal = HKQuantity(unit: HKUnit.countUnit(), doubleValue: goal)
 
activityRing.setActivitySummary(summary, animated: true)

That’s pretty much it.

Social Share Toolbar

Watch OS 2: Refreshing Apple Watch complication

To make WCSession work fine with Complications we have to use transferCurrentComplicationUserInfo on the iPhone side.
So here’s how to send updated dictionary from iPhone

// update complication
if session.watchAppInstalled {
    session.transferCurrentComplicationUserInfo(dataDictionary)
}

Let’s get back to Apple Watch Extension, here’s what should be in the InterfaceController which uses WCSession to subscribe on updates:

func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) {
    if let dateString = userInfo["dataKey"] as? String {
         // save new value to user defaults
         let defaults = NSUserDefaults.standardUserDefaults()
         defaults.setObject(dateString, forKey: "dataKey")
 
         // reload complication data
         reloadComplications()
     }
 }
 
func reloadComplications() {
    let server = CLKComplicationServer.sharedInstance()
    guard let complications = server.activeComplications where complications.count > 0 else {
        return
    }
 
    for complication in complications  {
        server.reloadTimelineForComplication(complication)
    }
}

That’s basically it, now we can get these values from the Cache in the Complication itself.

Social Share Toolbar

watchOS 2: Writing a WatchKit Complication

How to create custom WatchKit Complication which could be easily added to Apple Watch face.
This is one of the extremely exciting new additions to the WatchKit Framework in watchOS 2 – ability to add custom complications to the clock faces provided by Apple.

First let’s add Complication Data Source

import ClockKit
 
class Complication: NSObject, CLKComplicationDataSource {
 
    func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
        handler(nil)      
    }
 
    func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {
        handler(nil)
    }
 
    func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
        handler(CLKComplicationPrivacyBehavior.ShowOnLockScreen)
    }
 
    func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineEntry?) -> Void) {
        handler(nil)
    }
 
    func getTimelineEntriesForComplication(complication: CLKComplication, beforeDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {
        handler(nil)
    }
 
    func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {
        handler([])
    }
 
    func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
        handler([CLKComplicationTimeTravelDirections.None])        
    }
 
    func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
        handler(NSDate())
    }
 
    func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
        handler(NSDate())
    }
}

Let’s register it in the info.plist, make sure, that the following properties are set correctly
CLKComplicationPrincipalClass set to e.g. “$(PRODUCT_MODULE_NAME).Complication”
CLKComplicationSupportedFamilies has at least one value – CLKComplicationFamilyCircularSmall
RemoteInterfacePrincipalClass set to e.g. $(PRODUCT_MODULE_NAME).InterfaceController

Let’s update our data source template to provide some percentage like data, let say we have goal of 10 something and right now our progress is 8/10 – let’s render it (let’s make data static not to overcomplicate the example):

import ClockKit
 
class Complication: NSObject, CLKComplicationDataSource {
 
    func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
        // Update hourly
        handler(NSDate(timeIntervalSinceNow: 60*60))
    }
 
    func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {
        var template: CLKComplicationTemplate? = nil
        switch complication.family {
        case .ModularSmall:
            template = nil
        case .ModularLarge:
            template = nil
        case .UtilitarianSmall:
            template = nil
        case .UtilitarianLarge:
            template = nil
        case .CircularSmall:
            let modularTemplate = CLKComplicationTemplateCircularSmallRingText()
            modularTemplate.textProvider = CLKSimpleTextProvider(text: "--")
            modularTemplate.fillFraction = 0.7
            modularTemplate.ringStyle = CLKComplicationRingStyle.Closed
            template = modularTemplate
        }
        handler(template)
    }
 
    func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
        handler(CLKComplicationPrivacyBehavior.ShowOnLockScreen)
    }
 
    func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineEntry?) -> Void) {
        if complication.family == .CircularSmall {
            // these values should be fetched from somewhere...
            let progress = 8
            let goal = 10
 
            let template = CLKComplicationTemplateCircularSmallRingText()
            template.textProvider = CLKSimpleTextProvider(text: "\(progress)")
            template.fillFraction = Float(progress) / Float(goal)
            template.ringStyle = CLKComplicationRingStyle.Closed
 
            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template)
            handler(timelineEntry)
        } else {
            handler(nil)
        }
    }
 
    func getTimelineEntriesForComplication(complication: CLKComplication, beforeDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {
        handler(nil)
    }
 
    func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {
        handler([])
    }
 
    func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
        handler([CLKComplicationTimeTravelDirections.None])
    }
 
    func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
        handler(NSDate())
    }
 
    func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
        handler(NSDate())
    }
}

Feel free to use transferCurrentComplicationUserInfo for getting actual data, or simply get the data from NSCache().

Social Share Toolbar

swift: How to render a UIView to a UIImage

You can render any UIView into UIImage in just several lines of code. Never mind subviews – that will be handled automatically. Here’s the code:

 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, true, 0)
    view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

For sure you can extend UIImage for convenience

import UIKit
 
 
extension UIImage {    
    convenience init(view: UIView) {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, true, 0)
        view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(CGImage: image.CGImage!)
    }
}

After that you’ll need just:

 
    UIImage(view: someChartView)

That’s it!

P.S. Available from iOS 7.0

Social Share Toolbar