Slide 1

Slide 1 text

BUILDING WATCHOS APPS MOBILEOPTIMIZED 2015 BORIS BÜGLING - @NEONACHO

Slide 2

Slide 2 text

COCOAPODS

Slide 3

Slide 3 text

CONTENTFUL

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

!!!!

Slide 6

Slide 6 text

ᴡᴀᴛᴄʜ

Slide 7

Slide 7 text

WATCHOS 1.X ▸ Notifications ▸ Glances ▸ WatchKit apps

Slide 8

Slide 8 text

NOTIFICATIONS

Slide 9

Slide 9 text

GLANCES

Slide 10

Slide 10 text

WATCHKIT

Slide 11

Slide 11 text

WATCHOS 2.X ▸ Apps run natively on the watch ▸ Custom complications

Slide 12

Slide 12 text

!!!

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

COMPLICATIONS

Slide 15

Slide 15 text

ARCHITECTURE

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

WATCHOS 2 Extension phone => watch

Slide 18

Slide 18 text

RESOURCES ▸ Interface.storyboard ▸ Asset catalogs

Slide 19

Slide 19 text

EXTENSION DELEGATE class ExtensionDelegate: NSObject, WKExtensionDelegate { func applicationDidFinishLaunching() { } func applicationDidBecomeActive() { } func applicationWillResignActive() { } }

Slide 20

Slide 20 text

INTERFACE CONTROLLER class InterfaceController: WKInterfaceController { override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) } override func willActivate() { super.willActivate() } override func didDeactivate() { super.didDeactivate() } }

Slide 21

Slide 21 text

WKINTERFACECONTROLLER ▸ Navigation ▸ Presentation ▸ Handoff ▸ Handle notification actions ▸ Communicate with parent app

Slide 22

Slide 22 text

DESIGN

Slide 23

Slide 23 text

If you measure interactions with your iOS app in minutes, you can expect interactions with your Watch app to be measured in seconds.

Slide 24

Slide 24 text

PRINCIPLES ▸ Lightweight interactions ▸ Holistic design ▸ Personal communication

Slide 25

Slide 25 text

LAYOUT ▸ based on horizontal or vertical groups ▸ very similar to UIStackView ▸ two device sizes (38mm and 42mm) ▸ edge-to-edge, bezel provides margins

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

SOME EXAMPLES

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

BUILDING A SIMPLE APP

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

WATCHPRESENTER ▸ Remote controls Deckset instead ▸ Direct connection to the Mac ▸ Shows a preview of the slides ▸ Measures heartrate to display the "most exciting" slide ▸ Taps you if you're running out of time

Slide 36

Slide 36 text

MULTIPEER CONNECTIVITY!

Slide 37

Slide 37 text

AVAILABLE FRAMEWORKS

Slide 38

Slide 38 text

CFNetwork.framework ClockKit.framework Contacts.framework CoreData.framework CoreFoundation.framework CoreGraphics.framework CoreLocation.framework CoreMotion.framework EventKit.framework Foundation.framework

Slide 39

Slide 39 text

HealthKit.framework HomeKit.framework ImageIO.framework MapKit.framework MobileCoreServices.framework PassKit.framework Security.framework UIKit.framework WatchConnectivity.framework WatchKit.framework

Slide 40

Slide 40 text

BT APIS ARE PRIVATE :(

Slide 41

Slide 41 text

OTHER OPTIONS ▸ NSURLSession via Wi-Fi ▸ WatchConnectivity.framework to talk via the phone

Slide 42

Slide 42 text

HEALTHKIT.FRAMEWORK let anchorValue = Int(HKAnchoredObjectQueryNoAnchor) let sampleType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate) let heartRateQuery = HKAnchoredObjectQuery(type: sampleType!, predicate: nil, anchor: anchorValue, limit: 0) { (query, sampleObjects, deletedObjects, newAnchor, error) -> Void in guard let heartRateSamples = sampleObjects as?[HKQuantitySample] else {return} let sample = heartRateSamples.first let value = sample!.quantity.doubleValueForUnit(self.heartRateUnit) print(value) } heartRateQuery.updateHandler = // ...

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

HEALTHKIT.FRAMEWORK ▸ not usable in the Watch simulator

Slide 45

Slide 45 text

TAPTIC ENGINE typedef NS_ENUM(NSInteger, WKHapticType) { WKHapticTypeNotification, WKHapticTypeDirectionUp, WKHapticTypeDirectionDown, WKHapticTypeSuccess, WKHapticTypeFailure, WKHapticTypeRetry, WKHapticTypeStart, WKHapticTypeStop, WKHapticTypeClick } WK_AVAILABLE_WATCHOS_ONLY(2.0); WKInterfaceDevice.currentDevice().playHaptic(.Start)

Slide 46

Slide 46 text

BUT ALSO NOT USABLE IN THE SIM

Slide 47

Slide 47 text

SPOTIFY REMOTE

Slide 48

Slide 48 text

DEMO

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

TIPS

Slide 53

Slide 53 text

printf DEBUGGING IS GREAT!

Slide 54

Slide 54 text

MMWORMHOLE ▸ watchOS 1.0: CFNotificationCenter ▸ watchOS 2.0: WatchConnectivity.framework

Slide 55

Slide 55 text

FORCE QUIT APPS ▸ Long press until "reboot" menu ▸ Long press again

Slide 56

Slide 56 text

IF IN DOUBT, REBOOT THE WATCH :)

Slide 57

Slide 57 text

WHAT HAVE WE LEARNED? ▸ Code isn't very different from iOS apps ▸ But design very much is ▸ Rethink your app for the watch, don't port it ▸ If you can't - maybe you don't need a watch app

Slide 58

Slide 58 text

Don’t be afraid to not ship. @orta

Slide 59

Slide 59 text

THANK YOU!

Slide 60

Slide 60 text

▸ https://developer.apple.com/watch/human-interface-guidelines/ ▸ https://developer.apple.com/library/prerelease/watchos/ documentation/General/Conceptual/AppleWatch2TransitionGuide/ ▸ https://github.com/shu223/watchOS-2-Sampler ▸ http://www.kristinathai.com/category/watchkit/ ▸ https://realm.io/news/watchkit-mistakes/

Slide 61

Slide 61 text

@NeoNacho [email protected] http://buegling.com/talks