Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Practical WatchKit

Practical WatchKit

Given at NSLondon on 23/04/2015.

Neil Kimmett

April 23, 2015
Tweet

More Decks by Neil Kimmett

Other Decks in Technology

Transcript

  1. PRACTICAL WATCHKIT
    BY
    @NEILKIMMETT

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. mandsdigital.com

    View Slide

  6. View Slide

  7. View Slide

  8. View Slide

  9. HOW?

    View Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. WKInterfaceButton

    View Slide

  15. class WKInterfaceButton : WKInterfaceObject {
    func setTitle(title: String?)
    func setAttributedTitle(attributedTitle: NSAttributedString?)
    func setBackgroundColor(color: UIColor?)
    func setBackgroundImage(image: UIImage?)
    func setBackgroundImageData(imageData: NSData?)
    func setBackgroundImageNamed(imageName: String?)
    func setEnabled(enabled: Bool)
    }

    View Slide

  16. button.setText("I'm a button")

    View Slide

  17. View Slide

  18. View Slide

  19. View Slide

  20. View Slide

  21. View Slide

  22. View Slide

  23. View Slide

  24. SHARED APP GROUP

    View Slide

  25. NSUSERDEFAULTS
    let group = "group.me.kimmett.pushthebutton"
    let defaults = NSUserDefaults(suiteName: group)
    defaults?.setInteger(42, forKey: "IMPORTANT_NUMBER")
    defaults?.integerForKey("IMPORTANT_NUMBER") // 42

    View Slide

  26. NSFILEMANAGER
    let group = "group.me.kimmett.pushthebutton"
    let manager = NSFileManager.defaultManager()
    if let dir = manager.containerURLForSecurityApplicationGroupIdentifier(group) {
    // do something with dir
    }

    View Slide

  27. CORE DATA?

    View Slide

  28. CORE DATA
    if let dir = manager.containerURLForSecurityApplicationGroupIdentifier(group) {
    let url = dir.URLByAppendingPathComponent(“Database.sqlite”)
    let coordinator = …
    coordinator.migratePersistentStore(store,
    toURL: url,
    options: nil,
    withType: NSSQLiteStoreType,
    error: &error)
    }

    View Slide

  29. View Slide

  30. “on Yosemite and iOS 8, the method
    discards many-to-many relationships”
    — http://mjtsai.com/blog/2014/11/22/core-data-relationships-data-
    loss-bug/

    View Slide

  31. FIXED IN IOS 8.2

    View Slide

  32. MOVE THESE FILES
    .sqlite
    .sqlite-wal
    .sqlite-shm

    View Slide

  33. REAL TIME SYNC?

    View Slide

  34. REAL TIME SYNC
    ▸ MMWormhole
    https://github.com/mutualmobile/MMWormhole
    ▸ WFNotificationCenter
    https://github.com/DeskConnect/WFNotificationCenter

    View Slide

  35. WKINTERFACECONTROLLER
    class func openParentApplication(
    userInfo: [NSObject : AnyObject],
    reply: (([NSObject : AnyObject]!, NSError!) -> Void)?) -> Bool
    UIAPPLICATIONDELEGATE
    func application(application: UIApplication,
    handleWatchKitExtensionRequest: [NSObject : AnyObject]?,
    reply: (([NSObject : AnyObject]!) -> Void)!)

    View Slide

  36. OPENPARENTAPPLICATION
    var task: UIBackgroundTaskIdentifier
    task = application.beginBackgroundTaskWithExpirationHandler {
    reply([:])
    application.endBackgroundTask(task)
    task = UIBackgroundTaskInvalid
    }
    // do something with userInfo
    reply(…)
    application.endBackgroundTask(task)
    task = UIBackgroundTaskInvalid

    View Slide

  37. ONE WEIRD TRICK...
    “…you have to begin – and end, after two seconds – an empty
    background task right at the beginning of the delegate method.”
    — http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-
    trick-to-fix-openparentapplicationreply

    View Slide

  38. ONE WEIRD TRICK...
    var bogusTask: UIBackgroundTaskIdentifier
    bogusTask = application.beginBackgroundTaskWithExpirationHandler {
    application.endBackgroundTask(bogusTask)
    }
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(2 * Double(NSEC_PER_SEC)))
    dispatch_after(time, dispatch_get_main_queue(), {
    UIApplication.sharedApplication().endBackgroundTask(bogusTask)
    })
    // do your actual work

    View Slide

  39. HANDOFF

    View Slide

  40. WKINTERFACECONTROLLER
    func updateUserActivity(type: String,
    userInfo: [NSObject : AnyObject]?,
    webpageURL: NSURL?)
    UIAPPLICATIONDELEGATE
    func application(application: UIApplication,
    continueUserActivity: NSUserActivity,
    restorationHandler: ([AnyObject]!) -> Void) -> Bool

    View Slide

  41. DESIGN TIPS

    View Slide

  42. BLACK IS THE NEW WHITE

    View Slide

  43. BLACK IS THE NEW WHITE

    View Slide

  44. BLACK IS THE NEW WHITE

    View Slide

  45. View Slide

  46. View Slide

  47. REDUCE "TAP DISTANCE"

    View Slide

  48. REDUCE "TAP DISTANCE"

    View Slide

  49. View Slide

  50. REDUCE PADDING

    View Slide

  51. REDUCE PADDING

    View Slide

  52. REDUCE PADDING

    View Slide

  53. REDUCE PADDING

    View Slide

  54. REFERENCES
    ▸ “Core Data Relationships Data Loss Bug” by Michael Tsai
    http://mjtsai.com/blog/2014/11/22/core-data-relationships-data-
    loss-bug/
    ▸ “Tap Distance” by David Smith
    http://david-smith.org/blog/2015/02/03/ailw-tap-distance/

    View Slide

  55. REFERENCES
    ▸ “One weird trick to “fix” openParentApplication:reply:” by Brian
    Gilham
    http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-
    trick-to-fix-openparentapplicationreply

    View Slide

  56. SLIDES
    http://kimmett.me/talks/practical-watchkit.html

    View Slide

  57. QUESTIONS?

    View Slide