標籤:
開始學習 WatchKit!
更新於2015年1月19日:經過了Xcode 6.2 Beta版的測試; 沒有項目/代碼更改需要。 記住要使用蘋果最新的測試版!
iOS開發人員歡欣鼓舞 - WatchKit終於來了!
WatchKit是蘋果伴隨著的Xcode 6.2測試版發布的、用於建立Apple Watch應用程式的新架構和相關技術的開發包。
在這個WatchKit教程中,您將使用 Swift 建立第一個WatchKit應用程式。 具體來說,您將開發一個比特幣價格跟蹤應用程式,同時建立一個與之一同使用的 Watch 應用程式。
在這個過程中,您將學習瞭解如何架構WatchKit應用程式,怎麼讓一些新WatchKit特有的UI控制項工作起來,WatchKit布局,等等。
讓我們開始吧! ┗(°0°)┛
註:由於Apple Watch SDK文檔是向公眾開放的,我們還沒有聽到任何矛盾的規定,我們假設現在聊WatchKit是合適的。 如果有人聽到對此事的官方訊息,請告訴我們!
入門
首先, 下載本WatchKit教程的起始項目,:
http://cdn2.raywenderlich.com/wp-content/uploads/2014/11/BitWatch-Starter.zip
開啟起始項目,然後選擇iPhone 6模擬器作為運行目標。 構建和運行應用程式來感受一下吧。 該應用程式使用Bitcoin 平均價格指數 API來擷取最新的比特幣的價格並在螢幕上顯示出來。
你是一個Bitcoin的億萬富翁嗎?
現在是時候開始在Watch上跟蹤你的比特幣的財富了!
在Xcode中,定位到File\New\Target…並選擇了iOS\Apple Watch\Watch App應用程式模板。
一個Watch應用程式可以同主體iOS捆綁在一起,像擴充一樣工作。但這個選項將建立一個單獨的target。 單擊Next繼續。
在下面的螢幕中,Xcode將自動填滿許多的值,有些值無法改變,比如產品名稱。
確保語言設定為Swift,並且Include Notification Scene 和Include Glance Scene選項都不要被選中。 單擊Finish,Xcode中會設定target和一些Watch介面的基本模板檔案,隨時等待您上手開發!
如果你看一下項目導航器,你會看到有兩個不同的分組:
Watch分組
Watch應用程式分組包含只是storyboard and image assets…並沒有代碼!可以認為是您的應用程式的“視圖”。
該WatchKit Extension包含一些事件代碼,這些代碼在像應用程式啟動、按鈕輕擊,或switch變化這類事件中事件執行。 可以認為這是您的應用程式的“控制器和模型”。
WatchKit_03
直到我們能夠接觸“Native”的Watch應用之前,最好把這種設定方式認定為:Watch是從擴充控制的第二個較小的螢幕。 事實上,模擬器把Watch只是當一個外接顯示器,可以看到開始添加和測試介面對象。
註:Watch應用程式的術語跟iOS和Mac應用程式略有不同,不是視圖、控制器和視圖控制器,而是有介面,介面對象和介面控制器。
Watch介面
當設計你的Watch應用程式介面時,您可以使用Storyboard和Interface Builder,就像你的iOS應用程式一樣。 看這裡,開啟BitWatch Watch應用程式組,並選擇Interface.storyboard。
Watch storyboard1
你會看到在故事板中看到一個空的介面控制器。 讓我們添加一些控制項吧!
開始從物件程式庫拖動Label到介面上。 然後,在其下放一個按鈕。
手錶storyboard2
您可能會在這裡注意到有一些奇怪的地方 - 你可以在故事板周圍拖動介面元素,但只能垂直(不是水平)地改變自己的位置,並一個一個疊加地垂直鎖定控制項。
換句話說,你可以把標籤放在按鈕上,或者把按鈕放在標籤上,但是你不能,像你可以在iOS上一樣“隨意地”拖動元素。 習慣使用在iOS使用自動布局的你可能會做出如下這幅表情:
ConfusedGuy
原來,在Apple Watch上並沒有自動布局,它在布局和定位上有自己的機制。 讓我們一起來看看。
定位
這不是很像自動布局,但在你的Watch應用程式中,每一個介面元素都必須“固定”到某些東西上,不管是螢幕邊緣或其他對象。 這將決定其最終的位置。
預設情況下,兩個對象被定位在頂部; 可以改變它們的順序,讓其中一個在另一個的頂上,但是它們的位置將相對於螢幕的頂部放置。
你可以使用 Utilities 面板中的Attributes inspector來調整介面元素的位置。 選擇標籤並改變其Horizontal位置屬性為Center ,讓Vertical位置屬性為Top。
Watch center top
接下來,選擇按鈕,改變其Horizontal位置屬性為Center ,其Vertical位置屬性為Bottom 。
Watch storyboard3
如果用自動布局術語來描述的話,你可以認為這是將介面元素固定到布局的頂部和底部。 由於Watch的螢幕是如此小,所以它簡單到只是選擇兩個位置來進行調節 - 水平和垂直。 你會看到它是多麼容易地相對彼此來對自己進行位置定位。在後面,你可以添加更多的東西到介面上。
格式化
首先,讓我們設定一些文本和格式來使用介面看起來漂亮一些,並探討一些在Attributes inspector中的使用的其他選項。
選擇標籤,並確保在Utilities中的Attributes inspector處於開啟狀態。 該標籤將顯示Bitcoin的價格,所以設定文本為 $ 0.00,選擇置中對齊。 通過單擊字型域的“T”表徵圖,開啟字型彈出塊,並設定值為Custom, Avenir Next, Demi Bold, 尺寸為 30。
Watch 標籤字型
選擇按鈕,改變其標題為Refresh 。 更改其字型為Custom, Avenir Next, Medium, 尺寸16。
手錶按鈕
這看起來很不錯!
手錶storyboard4
請注意,您可以在運行時通過代碼來改變如文本、標題和顏色這類屬性,但你只可以在故事板中修改字型和定位屬性。 所以,如果你已經習慣了在代碼中設定您的布局的話。相比開發 iOS 應用程式,開發 Watch 應用程式需要你多花一點時間在Interface Builder上。
註:又一個友好的提醒,WatchKit是β版狀態 -因此有可能蘋果在將來某個時候將可以在代碼中開放介面對象的更多方法和屬性。
Action 和 Outlet
Action 和 Outlet的工作就像你所期望的那樣,讓您從代碼中訪問介面元素和處理使用者動作,如按鍵。
如果你覺得麻煩了,把這些東西關聯起來有點奇怪,因為故事板在Watch App target 中,而代碼則在WatchKit Extension target 中。
怎麼能跨 target 關聯Action 和Outlet 呢? 甚至能跨裝置關聯呢?因為應用程式是在Watch 上,而擴充在手機上!
幸運的是,這神奇的一部分是蘋果在幕後處理好了的,所以你不必擔心。
遠程Action和Outlet? 藍芽魔法!
在幕後,蘋果公司負責所有在您WatchKit應用程式 和 iPhone WatchKit擴充之間的無線通訊,使用了藍芽技術。 很酷,不是嗎?
開啟Assistant編輯器,並確保InterfaceController.swift開啟。按下Ctrl鍵,從價格標籤拖動到InterfaceController類裡面,來定義建立一個Outlet,把它叫做priceLabel,然後單擊Connect 。
Watch Outlet
接下來,按住Ctrl,從按鈕拖動到類裡。 這一次,一定要選擇Action來建立一個方法,而不是Outlet。 將操作方法命名refreshTapped,然後單擊Connect 。
這就是到目前為止的介面。 現在是時候切換到代碼,並得到了一些資料顯示出來了!
基本的WatchKit代碼
起始項目包括一個名為BitWatchKit的架構,包含一些自訂代碼來擷取比特幣的價格。我們把這個代碼做在架構裡,因此它可以同時在iPhone應用程式中使用,在iPhone WatchKit擴充中也可以很容易地使用。
將這個架構添加到您的擴充中,開啟導航器中的專案檔,並選擇BitWatch WatchKit擴充的target。選擇General選項卡,然後向下滾動到Linked Frameworks and Libraries部分。
Watch擴充
點擊架構列表下的+按鈕。你會看到一個視窗,其中列出了可用來添加的架構,你應該看到BitWatchKit.framework就在列表的頂部。選擇它,然後單擊添加。
Watch架構
現在,架構添加進來了,你可以用一些真實的資料更新您的Watch介面!
切換到InterfaceController.swift的WatchKit Extension組。 將以下import語句添加到檔案的頂部:
import BitWatchKit
這將允許您訪問架構中定義的Tracker類。
接下來,在類定義中添加以下屬性:
let tracker = Tracker()
var updating =false
你需要使用Tracker 執行個體來通過網路獲得比特幣價格。您將使用updating變理來標識,是否有一個掛著的“更新價格”的請求。
添加下面的輔助方法到類中:
private func updatePrice(price:NSNumber){
priceLabel.setText(Tracker.priceFormatter.stringFromNumber(price))
}
這個方法需要一個NSNumber值來更新Watch 上的標籤。Tracker還包括一個方便的數字格式,將使用一些像93.1這樣的數字能轉換成一個字串,如“$93.10”。
增加一個輔助方法到類中:
private func update(){
// 1
if!updating {
updating =true
// 2
let originalPrice = tracker.cachedPrice()
// 3
tracker.requestPrice {(price, error)-> ()in
// 4
if error ==nil{
self.updatePrice(price!)
}
self.updating =false
}
}
}
讓我們一步一步地回顧一下:
1、運行快速檢查,以確保你沒有在更新中。
2、緩衝目前的價格,所以只需要在價格發生變化更新UI介面。
3、requestPrice()是Tracker上的方法,通過網路請求來擷取最新比特幣價格。 一旦完成,它執行了一個閉包。
4、如果請求成功,所有你需要做的是調用 updatePrice()來更新標籤。
現在,你只需要從某處調用這些方法來獲得真實的資料,顯示在介面上。
介面生命週期
你的第一個機會,就是在awakeWithContext(_:)中設定您的介面元素,而此時,整個介面被載入,並且Action和Outlet被串連起來。
這意味著你可以設定介面對象,並開始顯示資料。然而,到目前為止該介面還不必要放到Watch上去!因為重要的是使事情達到一個合理的狀態:你可能不希望進行昂貴的操作,如進行網路調用。
將以下內容添加到awakeWithContext 結尾處:
updatePrice(tracker.cachedPrice())
這將使用先前緩衝值(如果存在的話)更新價格標籤。因為這個值是由被Tracker 所緩衝的,它是本機資料,擷取起來代價很小。
以下內容添加到willActivate() 的尾部
update()
willActivate就像iOS 中的viewWillAppear。並且意味著介面即將啟用,並出現在Watch中。這是一個很好的重新整理資料的訊號,因此在這裡調用update() ,以開始網路請求,並且更新標籤。
最後,將相同的程式碼添加到refreshTapped :
update()
當使用者點擊Refresh,你想要同樣的事情發生:調用update() ,並顯示一些新的資料。
測試您的應用程式
要測試你的Watch應用程式,你需要讓Watch作為外部顯示器。 如果你的iPhone模擬器有應用在運行,切換到它。 否則,構建和運行應用程式,在Xcode把它停掉,然後再切換回iOS模擬器。在菜單中,導航到Hardware\External Displays,並選擇一個Apple Watch選項。
Watch模擬器
你應該現在有兩個模擬器視窗 - 一個顯示了iPhone,一個是Watch所用的。
返回到Xcode中,選擇工具列中的BitWatch Watch App 方案,並選擇iPhone 6模擬器。
Watch方案
構建並運行,然後切換到模擬器。你應該在蘋果Watch 看到Bitcoin的資料!
手錶APP1
更多的介面
現在,您已經基本入門了,現在來看看你可以使用介面來做的更多的東西。
在本應用中,還有兩個你想要在Watch 上實現的元素:
最後更新時間
向上/向像,以顯示價格是否增加或減少
要做到這一點,你首先需要將映像添加到asset目錄。開啟BitWatch Watch App組的Images.xcassets。這裡要小心:在項目中,有 3個 Images.xcassets檔案,所以一定要確保你在正確的組!
起始項目包括兩個影像檔:[email protected]和[email protected]。從finder視窗,拖動這兩個檔案到映像集合列表中。
看asset
注意,映像唯一的@2x的變體也包括在內。在WatchKit 中你只需要@2x 的映像– 因為沒有非Retina屏的Apple Watch!
接下來,再次開啟Interface.storyboard,返回到布局。
將另一個標籤拽到介面上,並把它放到Reresh按鈕上面。設定標籤文本為Last Updated ,並且將字型設定為Custom, Avenir Next, Regular, 和尺寸 13。也改變文本對齊為Center。
對定位的設定,改變Horizontal位置屬性設定為Center和Vertical位置屬性設定為Bottom。
手錶storyboard5
你可能會想:如果Refresh按鈕、這個新標籤的定位屬性均設定為底部,Watch是知道如何,用什麼樣的順序來放置他們?
在iOS上,在文檔大綱中,視圖順序確定了z-order,或者確定了哪個視圖“在頂部”或在別的視圖“後面”。而針對Watch介面,介面元素不重疊,所以沒有必要跟蹤z-order。相反,在文檔概要中的順序反映了垂直的從頂部至底部的順序(結合垂直對齊設定)。
Watch 外觀
要明白我的意思,在大綱中交換Refresh和Last Updated控制項的順序- 你會看到它們在Interface Builder中直觀地交換好了。當你完成時,再換回來
分組
到目前為止,你的Watch 介面包括堆積在彼此頂部的介面對象。那麼,我們如何一個個並排對象呢?
供您使用的另一個對象是組 。組就像容器,你可以把介面對象放在他們裡面。 然而,它們也具有是否應該水平或垂直地布置它們所包含元素的設定。你可以通過在組中嵌套組,使用不同布局來獲得各種不同的介面放置!
註:組可以是有背景顏色和圖片的介面元素。在這個應用程式中,除了它們是如何對布局做貢獻之外,對使用者是不可見的(譯者註:因為本應用中的組,沒有背景顏色和圖片,所以不可見)!
下面是看起來像在iPhone應用程式中的價格上升/下降的指標:
Watch app剪頭
所以,總體規劃是在標籤旁邊放置一個圖片。
將一個新組從物件程式庫拖動到故事板中,並把它放在price標籤和last updated標籤之間。在Attributes inspector中,確保組的布局設定為Horizontal 。
手錶storyboard6
接下來,將一個圖片控制項從物件程式庫拖動到組控制項裡面。然後把一個新的標籤拖動到組中,並將其放置在映像的右側。
Watch storyboard7
這樣就有兩個對象並排在一起,但現在問題是,如何設定它們的位置和大小。
位置和大小
選擇標籤並同時改變其Horizontal和Vertical 位置屬性為Center 。對圖片控制項做相同的操作。
由於映像和標籤是一個組內,它們在組中置中,而沒有在外部故事板作為一個整體的對象中。這意味著,組四處移動,以及因為某種原因被調整尺寸,映像和標籤都會停留在組的正中心。
預設情況下,大多數介面對象都可將其size屬性設定為Size to Fit Content。這非常適用於標籤,因為文本可能會改變。然而,箭頭圖片是在資源套件中的,並且有一個已知大小,你可以在故事板中設定大小。這意味著Watch在後面將不需要計算尺寸。
選擇映像,並且在Attributes inspector中找到Size部分。更改Width設定為Fixed Width 和高度設定為 Fixed Height。同時設定width和height值為32。
手錶大小
整合介面
如果只是把標籤放到故事板中,標籤的文本不會改變。改變其文本為 1BTC,並且將其字元修改為:Custom, Avenir Next, Regular, 和尺寸 13。
此映像將根據先前比特幣的價格而改變(譯者註:以前價格比當前價格低還是高),因此你需要一個outlet。開啟輔助編輯器,按下Ctrl鍵,從映像拖動到類定義中。命名為image outlet ,然後單擊Connect 。
對於“Last Updated”標籤,你需要另外一個 outlet 。按下Ctrl鍵,從標籤拖動到類定義,並命名為lastUpdatedLabel,然後單擊Connect 。
這就是它的所有介面– 在開始跟蹤你的Bitcoin 資產前。如果從代碼更新布局,需要更多一些的代碼和一些技巧。
整合代碼
開啟InterfaceController.swift。 有兩個新的事情要處理:“lastupdated”標籤和映像。
添加下面的輔助方法到類中:
private func updateDate(date:NSDate)
{
self.lastUpdatedLabel.setText("Last updated \(Tracker.dateFormatter.stringFromDate(date))")
}
此方法像 price標籤更新一樣,更新last updated 標籤。同樣,Tracker具有格式化器對象,在這種情況下,將格式化日期,以只顯示時間。
增加一個輔助方法到類中:
privatefunc updateImage(originalPrice: NSNumber, newPrice: NSNumber) {
if originalPrice.isEqualToNumber(newPrice){
// 1
image.setHidden(true)
} else {
// 2
if newPrice.doubleValue >originalPrice.doubleValue {
image.setImageNamed("Up")
} else {
image.setImageNamed("Down")
}
image.setHidden(false)
}
}
此方法將比較原來的價格與新的價格。
1、如果這兩個價格都是一樣的,隱藏的箭頭映像。
2、如果這兩個價格不一樣,根據價格的變化,設定圖片為“向上”或者“向下”,同時取消隱藏映像,使其再次可見。
調用setHidden將導致布局重排。記得如何將圖片和“1 BTC”標籤都置中放在組裡面嗎?當你隱藏圖片,這將會使標籤左側空出額外的空間來。然而,該介面足夠聰明,重新計算布局,並且移動標籤,以讓標籤仍然是組內部的中心。
注意:您可以隱藏的東西,並通過使用setAlpha來設定介面對象的alpha屬性為0,而仍然讓他們“佔用空間”。
現在,輔助方法到位,你需要調用它們。
下面的幾行添加到awakeWithContext 的尾部:
image.setHidden(true)
updateDate(tracker.cachedDate())
因為你在啟動時,沒有任何以前的價格資訊,在開始時您有一個隱藏的映像。價格從緩衝中來,當然你也可以從緩衝中去抓取日期。
接下來,找到update()並添加以下行到最裡面if塊裡。就是有if error == nil {條件的那個塊:
self.updateDate(NSDate())
self.updateImage(originalPrice, newPrice:price!)
這將更新 last updated標籤來顯示目前時間。在這裡,也同時得到先前的價格和新價格,然後如果價格發生了變化可以使用updateImage顯示向上或向下箭頭的映像。
構建和運行監視應用程式看看模擬器。
你應該看到當前價格跟之前一樣顯示。 因為你已運行一次應用程式,應該已經有了一個緩衝價格,如果緩衝價格與當前價格不同,你應該看到一個向上或向下箭頭了。
來源資料每分鐘更新一次,這樣你就可以等待一分鐘,然後點擊Refresh按鈕,獲得最新的比特幣的價格。你能負擔得起的純金Apple Watch版本了嗎?]
下面如何開始?
這裡是上面WatchKit教程的最後一個樣本項目。:
http://cdn1.raywenderlich.com/wp-content/uploads/2014/11/BitWatch-Final-1.2.zip
恭喜你 - 你現在知道製作WatchKit應用程式的基礎知識了!
但是,還有很多東西要學 -包括額外的介面對象,導航和切換傳遞(指Hand Off)。並記住,這僅僅是學習了一種類型的應用程式WatchKit的製作 - 你也可以製作Glances(類似於Today擴充),或自訂可操作的推播通知等。
譯者:優才網
Greg Heo
原文:http://www.raywenderlich.com/89562/watchkit-tutorial-with-swift-getting-started
【轉】使用 Swift 開發WatchKit入門教程