watchOS

一起動手做一個簡單的Apple Watch筆記App

一起動手做一個簡單的Apple Watch筆記App
一起動手做一個簡單的Apple Watch筆記App
In: watchOS

我們將會開發一隻很簡單的 iPhone + Watch App,你可以在iPhone App輸入簡訊然後顯示在Apple Watch上。從中理解如何利用NSUserDefaults 及 App Group 功能把iPhone app的資料分享至 Watch App。

註:本範例使用Xcode 7.0 (7A220) 與 iOS 9 開發。

新增一個單一畫面樣板的專案

事不宜遲,首先打開Xcode,選擇 Create a new Xcode project。點選 iOS > Application > Single View Application,然後按 Next。

xcode project template

專案名稱(Product Name)取名為WatchSimpleNote、組織名稱(Organization Name)與Organization Identifier(組織識別)請自行命名,並選擇Swift作為開發語言、Devices裝置為iPhone,Use Core Data的選項此範例不會使用到,無需勾選,之後按 Next 繼續。

設定App Groups

由於我們使用到NSUserDefaults作為資料的存放方式,我們必須去設定App Groups的功能。選擇專案後,依照圖片所示選擇Targets > Capabilities > App Groups,將off啟動為on的狀態。啟動App Group是由於我們需要將iPhone app的資料分享至Apple Watch App。

app group

之後,選擇你要使用的開發者帳號。

app group - select a development team

接著再空的列表中按下+,來新增一個新的App Groups。App Groups需要有一組識別用的ID為group.開頭,並且在後面加上跟Bundle Identifier相同的反向域名。

app group - new container

完成後,便可以看到我們剛剛所新增的group.com.appcoda.WatchSimpleNote,勾選並使用他。

温馨提示:你要自訂一個獨一無二的名稱,不可以跟著範例一樣啊!

enable app group

在Apple Developer網站中,也可以看到我們所新增的group.com.appcoda.WatchSimpleNote

apple developer console

為專案新增WatchKit App

選擇File > New > Target。在iOS中選擇Apple Watch > WatchKit App for watchOS 1。由於本範例不會使用到Notification的功能,我們不需要勾選Include Notification Scene,之後按Finish繼續。

New watch app target

接著如前面一般,我們也要為WatchKit App啟動App Groups的功能,注意這邊的Target跟先前步驟不同。

add app group

這邊我們可以看到先前建立的group.com.appcoda.WatchSimpleNote,請勾選並使用他。

Enable app groups for watch app

佈置我們的storyboard

現在終於開始設計Watch App 介面。 開啟Main.storyboard,利用Xcode中所提供的元件庫,我們為手機介面建立了UILabelUITextFieldUIButton三個元件。

design watch app ui

稍微調整一下大小和擺放位置,並且加上一些顏色,在這邊我們將UILabel元件拉大,並將行數調整為6行。接著再UITextField元件中的Placeholder加上提示輸入字樣”type something here…”。最後,將三個元件選取後,按下右下方”Resolve Auto Layout Issues”裡的Add Missing Constraints。

Designing iphone app ui

處理完手機的部份後,我們開啟”WatchSimpleNote WatchKit 1 App”中的Interface.storyboard,來佈置手錶中的介面。一樣利用Xcode所提供的元件庫,我們在手錶上建立了一個Label和一個Button。

Watch app ui

自行加上喜歡的色彩後,將Label範圍拉大並且調整行數為6行。

watch app ui

將View和Controller建立關連

ViewController.swift中,建立三個介面與程式的關聯性 (包括兩個IBOutlet及一個IBAction):

@IBOutlet weak var label: UILabel!
@IBOutlet weak var textField: UITextField!
@IBAction func pressSubmit(sender: AnyObject) {
        
}

利用Assistant Editor模式建立IBOutletIBAction。只要按住control加滑鼠左鍵從Storyboard 中選取所需連結的元件並拖曳至ViewController.swift,鬆開按鈕之後,你就可以建立相關的outlet或action。

Connect outlets

接著開啟Interface.storyboard,也為我們手錶介面中的元件建立連結,搭配的controller為WatchSimpleNote WatchKit 1 Extension中的InterfaceController.swift。完成後,你會有一個IBOutlet及一個IBAction。

@IBOutlet var watchLabel: WKInterfaceLabel!
@IBAction func pressUpdate() {

}

connect outlet

實作NSUserDefaults

現在我們要依序建立需要的變數。利用NSUserDefaults來存放我們的Note內容。依序我們先於ViewController.swift中建立兩個常數,分別為:

  • groupID – 存放我們的App Groups ID 為group.com.appcoda.WatchSimpleNote
  • defaults – 使用NSUserDefaults的方法去讀取我們所指定的group

將這些功能寫在按鈕觸發的動作之中,當我們按下送出按鈕時將觸發下列程式碼:

@IBAction func pressSubmit(sender: AnyObject) {
    let groupID = "group.com.appcoda.WatchSimpleNote"
    if let defaults = NSUserDefaults(suiteName: groupID) {
        defaults.setValue(textField.text, forKey: "Note")
        label.text = textField.text
    }
}

defaults有讀取到對應的group時,我們透過defaults.setValue(textField.text, forKey: "Note")將textField中的文字存入NSUserDefaults中指定的group並且對應的Key為Note,然後label.text = textField.text會把我們所輸入的文字替換到Label上顯示。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var textField: UITextField!
    @IBAction func pressSubmit(sender: AnyObject) {
        let groupID = "group.com.appcoda.WatchSimpleNote"
        if let defaults = NSUserDefaults(suiteName: groupID) {
            defaults.setValue(textField.text, forKey: "Note")
            label.text = textField.text
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

再來我們於InterfaceController.swift實作讀取NSUserDefaults的部份。一樣我們建立兩個常數分別為:

  • groupID – 存放我們的App Groups ID 為group.com.appcoda.WatchSimpleNote
  • defaults – 使用NSUserDefaults的方法去讀取我們所指定的group

寫在按鈕的觸發中,當我們按下Update按鈕時,便會去讀取定的group,透過defaults?.stringForKey("Note")去撈取相對應Key為Note的資料,在利用watchLabel.setText()的方法將內容替換到Label中。

在這邊defaults後面的”?”是因為我們沒有使用跟先前if let ... {}相同的做法,因此必須加上”?”。

import WatchKit
import Foundation


class InterfaceController: WKInterfaceController {

    
    @IBOutlet var watchLabel: WKInterfaceLabel!
    @IBAction func pressUpdate() {
        let groupID = "group.com.appcoda.WatchSimpleNote"
        let defaults = NSUserDefaults(suiteName: groupID)
        watchLabel.setText(defaults?.stringForKey("Note"))
        
    }
    override func awakeWithContext(context: AnyObject?) {
        super.awakeWithContext(context)
        
        // Configure interface objects here.
    }

    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
        super.willActivate()
    }

    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
        super.didDeactivate()
    }

}

現在是時候試試我們的Watch app。你可以選擇 WatchSimpleNote WatchKit 1 App Scheme執行Watch app 程式。

run-watch-app

運行起來試試看吧,你是不是也完成了一個簡易的Apple Watch App呢?試試在iPhone app輸入簡訊,然後按Watch app 的Update按鈕,你的簡訊就會在出現!

watch-note-app-demo

從這裡出發

能夠初步了解到WatchKit和iPhone之間的資料交換,也許你可以試著使用 CoreData 或是 SQLite 的方式去存放資料,更可以搭配WCSession去做到更即時的資料交換唷!

供你參考,請從這裡下載本文的完整 Xcode 專案。別忘了更新專案裡面的 Bundle ID 及 App Groups ID。

作者
Max Chen
一名熱愛新技術的大學生,於就讀輔仁大學資管系期間曾任多門程式設計課程助教,專長為前端介面設計與iOS程式開發,目前於HackNTU 擔任iOS 課程講師及助教,並往UI/UX設計師與iOS開發者方向努力。可以透過LinkedIn與我聯繫。
評論
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。