WatchKit is Apple’s new framework and related technologies that allow you to create apps for the Apple Watch, released along with Xcode 6.2.

In this WatchKit tutorial, you’ll create your first WatchKit app with Swift. Specifically, you’ll take a Password Lock app, and make a Watch app that goes along with it.

Today we will develop a One Password like passcode lock screen app for the apple watch as shown below:

Password Lock Interface

Getting started

Open Xcode and create a new project by choosing the Single View Application template. Choose iPhone under “Devices”. Choose Swift as main language.

Templates

This app has nothing much to do with the iPhone screen and hence no modifications are required in the iPhone Storyboard. Finally move on to adding watch app extension ahead.

Adding Watch App target

Now press File -> Add Target -> Watch App.

screenshot4-e1417271969497

Press Next, We don’t need to mark “Include Notification Scene” and “Include Glance Scene” checkboxes.

watchKit

Let’s look around what Xcode has created for us.

We see that there’s a WatchKit Extension with all needed interface controllers (for main interface, notifications and glance).

There’s also a separate Watch App that contains only the storyboard and assets folder.

Password Lock WatchKit

Watch App Interface Builder Basics

Designing interfaces for Apple Watch is similar to designing for iOS, but a few things are simplified. 

1. The Object Library contains less objects, which are customised for Apple Watch (e.g Image or Table). A few objects are completely new (e.g menu or separator). 

2. Connecting IBOutlets and IBActions is same as for iOS.

3. Positioning views on screen is simplified. There is no frames, no autolayout and no view hierarchies. All items are stacked vertically on different lines – one below the other. There is also a possibility to use View Groups to layout items horizontally. The size and position of items can be configured in Attributes inspector.

All objects have to be added in Interface builder – new  objects cannot be added programmatically. The only option is to add all possible items in Interface builder and then show/hide them, when necessary. Hiding the object will free its space and other items will be laid out according to new space options.

Creating a Watch App

1. Open the storyboard of the Watch app (in our case Passcode Lock WatchKit App > Interface.storyboard). Select Home Interface Controller Scene. Open the Object Library and drag Buttons object to the scene as shown below.

2. Add needed outlets to those classes, all labels and buttons to the Interface.swift file located under Password Lock WatchKit Extension Folder.

    @IBOutlet weak var passcodeGroup: WKInterfaceGroup?
    @IBOutlet weak var animationGroup: WKInterfaceGroup?
    @IBOutlet weak var contentGroup: WKInterfaceGroup?

    @IBOutlet weak var keypadImage: WKInterfaceImage?

    @IBOutlet weak var entryIndicator1: WKInterfaceGroup?
    @IBOutlet weak var entryIndicator2: WKInterfaceGroup?
    @IBOutlet weak var entryIndicator3: WKInterfaceGroup?
    @IBOutlet weak var entryIndicator4: WKInterfaceGroup?
// MARK: - IBAction Methods (Passcode)

    @IBAction func didTap1() { addKeyEntry(1) }
    @IBAction func didTap2() { addKeyEntry(2) }
    @IBAction func didTap3() { addKeyEntry(3) }
    @IBAction func didTap4() { addKeyEntry(4) }
    @IBAction func didTap5() { addKeyEntry(5) }
    @IBAction func didTap6() { addKeyEntry(6) }
    @IBAction func didTap7() { addKeyEntry(7) }
    @IBAction func didTap8() { addKeyEntry(8) }
    @IBAction func didTap9() { addKeyEntry(9) }
    @IBAction func didTap0() { addKeyEntry(0) }

    @IBAction func didTapDelete() { removeKeyEntry() }
// MARK: - IBAction Methods (Content)

    @IBAction func didTapLock() { lock() }

3. After connecting all the outlets, add the following lines of code:

// MARK: - Private

    private func addKeyEntry(entry: Int) {
        keyEntrySequence.append(entry)
        println("PasswordSequence: \(keyEntrySequence)")
        updateEntryIndicators()
    }

    private func removeKeyEntry() {
        keyEntrySequence.removeLast()
        println("PasswordSequence: \(keyEntrySequence)")
        updateEntryIndicators()
    }

    private func updateEntryIndicators() {
        switch keyEntrySequence.count {
        case 4:
            startUnlockAnimation()
        case 3:
            entryIndicator4?.setHidden(true)
            entryIndicator3?.setHidden(false)
        case 2:
            entryIndicator3?.setHidden(true)
            entryIndicator2?.setHidden(false)
        case 1:
            entryIndicator2?.setHidden(true)
            entryIndicator1?.setHidden(false)
        case 0:
            fallthrough
        default:
            entryIndicator1?.setHidden(true)
        }
    }

    private func startUnlockAnimation() {
        passcodeGroup?.setHidden(true)
        animationGroup?.setHidden(false)

        keypadImage?.setImageNamed("Keypad") // Don't include the number
        //        keypadImage?.startAnimating()
        keypadImage?.startAnimatingWithImagesInRange(NSRange(location: 1, length: 30), duration: 1, repeatCount: 1)

        let delay = Int64(1 * NSEC_PER_SEC) // one second
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay), dispatch_get_main_queue()) {
            [unowned self] in
            self.keypadImage?.stopAnimating()
            self.unlock()
        }
    }

    private func unlock() {
        passcodeGroup?.setHidden(true)
        animationGroup?.setHidden(true)
        contentGroup?.setHidden(false)

        setTitle("Content")
        println("Unlocked")
    }

    private func lock() {
        passcodeGroup?.setHidden(false)
        animationGroup?.setHidden(true)
        contentGroup?.setHidden(true)

        setTitle("Passcode")
        println("Locked")

        // Reset the entry state
        keyEntrySequence = []
        entryIndicator1?.setHidden(true)
        entryIndicator2?.setHidden(true)
        entryIndicator3?.setHidden(true)
        entryIndicator4?.setHidden(true)
    }

Let’s break the above code into pieces and understand it.
The first two functions are addKeyEntry() & removeKeyEntry() which append or remove the Integer number pressed from the button. It basically adds or removes values from the [Int] Array named keyEntrySequence.
When the user taps a numbered button the indicator lines at the bottom of the screen start filling until 4 spaces and then a new screen appears.

The code can be modified inorder to match a particular password for giving access to the main screen just like One Password app.

TEST YOUR WATCH APP

  1. When you run the app you’ll see a blank view since our app doesn’t do anything except create the Watch App and the watch is shown in an External Display.
  2. Build and Run your app against the Watch App target.
  3. Then, switch over to your simulator and check that you have the External Display set for the watch. iOS Simulator > Hardware > External Displays (try both sizes to see how it looks).
  4. You should see your app in the Apple Watch simulator. Enter different password combinations and test it.

Password Lock Interface 

Here is the source code on Github for the tutorial above !

I hope you found this article helpful.  If you did, please don’t hesitate to share this post on Twitter or your social media of choice.  The blog is still pretty new, and every share helps.  Of course, if you have any questions, don’t hesitate to contact me on Twitter @swifty_os, and I’ll see what I can do.  Thanks!

Advertisements