本文是投稿文章,譯者:Swift_波(簡書)
原文地址
在這個過程中,你會學到:
如何為iOS app添加watchOS 2的target
如何在兩個target之間共享數據
如何添加一個watchOS 2界面控制器到Storyboard,並放置界面對象
如何創建WKInterfaceController的子類並連線
正式開始吧
首先下載教程的起始項目吧。
在Xcode中打開它然後編譯運行。你應該會看到一個空白界面:
這個項目沒有太多的文件,只包含一些你需要的最基本的文件。
添加WatchKit App
選擇File\New\Target…,在出現的對話框中選擇watchOS\Application\WatchKit App然後點擊Next:
在接下來的界面中,設置項目名字為Watch,確保語言設置為Swift,然後取消選中任何復選框。點擊Finish:
之後會詢問你是否想要激活watch scheme,你需要這麼做,所以確保選擇了激活:
祝賀,你剛剛創建了你的第一個手表app!這真的很容易。
你會注意到,這個操作實際上創建了兩個target,而不是一個,在項目導航中看到兩個對應的組。這是因為手表app的代碼實際是作為一個擴展形式存在的,類似iOS上的Today extensions。
當你在項目導航中點開Watch和Watch Extensions組的時候,你會看到所有storyboard放在Watch組,當前target創建的所有的類文件放在Watch Extensions組中:
你需要遵循如下的原則:任何你添加的代碼必須放在Watch Extension組中然後添加到Watch Extension target,而所有的assets或者storyboards需要放在Watch組裡。
小家務
在繼續前,你需要刪掉一些target模板添加的你不需要的文件。
在項目導航裡面右鍵點擊InterfaceController.swift然後選擇刪除。 當彈出提示,選擇Move to Trash來確保文件確實從項目中刪掉了:
下一步,打開Interface.storyboard,選擇其中僅有的界面控制器,按下backspace鍵來刪除它。現在就剩下一個空storyboard,或者是我認為的,一個空白畫布。
共享數據和代碼
起始項目包含一個記錄所有Aber航空公司航班信息的JSON文件,一個模型類表示飛行數據。這正是應該共享的數據,因為iOS app和手表app使用相同的模型類和數據-你記得DRY(不要寫重復的代碼)原則嗎?
在項目導航中點開Shared組然後選擇Flights.json。之後,在File Inspector中找到Target Membership區域,選中Watch Extension
文件現在應該被AirAber和Watch Extensions這兩個target所包含。 為其他Shared組的文件重復這個步驟,比如說Flight.swift。 這些都做完後,你可以開始開發航班詳情界面了!
構造界面
打開 Watch\Interface.storyboard,從對象庫拖一個界面控制器到storyboard裡面.選中這個界面控制器,打開屬性檢查器設置它的Identificer為Flight,然後勾選Is Initial Controller:
你設置的這個Identifier讓你可以在代碼中引用這個界面控制器。選中Is Initial Controller簡單告訴WatchKit你希望當應用程序啟動的時候首先顯示這個界面。
下一步,從對象庫中拖動一個組到界面控制器:
之後這個組會包含Aber公司的logo,航班號和路線。
選中這個組,在屬性檢查器的頂部改變它的Insets為Custom。這會顯示四個額外的文本框讓你可以手動的設置組的上下左右。設置Top為6:
這僅僅讓你的組到頂部有個額外的空隙。
下一步,拖動Image到組中。組會相應的收縮來改變Top inset(感謝Xcode!),之後在文檔大綱中檢查來確保Image是組的子節點,而不是同級:
現在需要顯示一張圖片,下載logo圖片然後把它拖動到Watch\Assets.xcassets中。這會創建一個新的logo圖片,存放在2x的部分。
為了給圖片染色,選中這張圖片,在屬性檢查器中修改Render As為Template Image。
重新打開 Watch\Interface.storyboard 選中之前的image.使用屬性檢查器,做如下的改變:
設置圖片為Logo - 當下拉列表沒有出現,你可以自己輸入;
設置Tint為#FA114F(也可以在顏色面板中輸入值);
設置Width為Fixed,值為40;
設置Height為Fixed,值為40。
屬性檢查器現在應該像下面這樣:
不要擔心看不到logo,因為Xcode設計時無法給模板圖片染色!
下一步,往已經存在的組中拖動另外一個組,確保它出現在image的右側,使用屬性檢查器設置Layout屬性為Vertical.同樣修改Spacing為0、Width為Size to Fit Content。然後拖動兩個label到新的組中,放置一個到另一個的下面。
選擇上面的label,使用屬性檢查器,設置文本為Flight 123,文字顏色為#FA114F。
選擇下面的label,設置文本為MAM to SFO。界面控制器最後看起來像下面這樣:
這些文本僅僅充當占位符,之後會被控制器中設置的文本取代。
下一步,拖動另一個組到界面控制器中,但是這次確保與第一個組同級。當不能設置組級別關系請使用文檔大綱(Document Outline)。
選中新的組,設置它的Layout為Vertical、Spacing為0。
現在,拖動三個label到新的組中:
確保label都在group中,而不是與group同級!
選擇頂部的label使用屬性檢查器修改它的文本為AA123 Boards。
選中中間的label,修改文本顏色為#FA114F,字體選擇System,Regulaer樣式和54.0的size.最後,修改Height為Fixed,值是44。
選中底部的label修改文本為On time,文本顏色為#04DE71。 你的界面控制器應該現在像下面這樣:
從對象庫中拖動一個新的組到下面的組,這次確保它是在子節點而不是在同級,之後向其中添加兩個label,你完全的界面對象關系應該像這樣:
使用屬性檢查器,設置左邊的label文本為Gate 1A。右邊的label設置為Seat 64A,之後設置它的Horizontal alignment為Right 完全的界面應該像如下這樣:
恭喜,你已經完成你的第一個watch app界面的布局了,現在是時候給它填充一些真實的數據然後在模擬器上運行。
創建控制器
在項目導航中右擊Watch Extensions組,選擇New File,在出現的對話框中選擇watchOS\Source\WatchKit Class然後點擊Next。命名新的類為FlightInterfaceController,確保它為WKInterfaceController的子類,語言設置為Swift:
點擊Next,之後是Create
可以看到新的文件在代碼編輯器中打開了,刪除其中的三個空方法,只剩下import語句和類定義。
添加這些Outlets到FlightInterfaceController的頂部:
@IBOutlet var flightLabel: WKInterfaceLabel! @IBOutlet var routeLabel: WKInterfaceLabel! @IBOutlet var boardingLabel: WKInterfaceLabel! @IBOutlet var boardTimeLabel: WKInterfaceLabel! @IBOutlet var statusLabel: WKInterfaceLabel! @IBOutlet var gateLabel: WKInterfaceLabel! @IBOutlet var seatLabel: WKInterfaceLabel!
這裡僅僅為之前的每個label添加一個Outlet。稍後會把他們連接起來。
下一步,在outlets下面添加flight屬性和對應的屬性觀察器:
// 1 var flight: Flight? { // 2 didSet { // 3 if let flight = flight { // 4 flightLabel.setText("Flight \(flight.shortNumber)") routeLabel.setText(flight.route) boardingLabel.setText("\(flight.number) Boards") boardTimeLabel.setText(flight.boardsAt) // 5 if flight.onSchedule { statusLabel.setText("On Time") } else { statusLabel.setText("Delayed") statusLabel.setTextColor(UIColor.redColor()) } gateLabel.setText("Gate \(flight.gate)") seatLabel.setText("Seat \(flight.seat)") } } }
會一步步講解發生的事情:
1.你定義了一個可選的屬性類型為Flight。這個類在Flight.swift中定義;
2.你添加了一個屬性觀察器,當屬性設值時候會觸發它;
3.在可選屬性中確保有一個真的flight而不是nil,當flight存在才會去設置labels的值;
4.使用flight的相關屬性去設置labels
5.如果航班被延誤,那麼你就將標簽的文本顏色改為紅色
在控制器第一次顯示時候設置航班。添加以下聲明:
override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) flight = Flight.allFlights().first! }
本後面的教程會修改為在上下文中傳遞值給它,但現在你只需要從共享的JSON文件中加載所有的航班,然後使用數組中的第一個。
在後面的教程你將學到更多關於awakeWithContext(_:)的知識,但是現在你僅僅需要知道它是界面控制器生命周期第一環節,一個設置flight值的地方。 現在僅剩最後一步你就可以編譯運行了,就是去連接outlets
連接outlets
打開 Watch\Interface.storyboard 選擇界面控制器,使用Identity Inspector,設置Class\Custom Class為FlightInterfaceController
下一步,右擊界面控制器頂部的黃色圖片彈出窗口:
現在,按下面的列表連接outlets:
boardingLabel: AA123 Boards
boardTimeLabel: 15:06
flightLabel: Flight 123
gateLabel: Gate 1A
routeLabel: MAN to SFO
seatLabel: Seat 64A
statusLabel: On time
在運行之前,有一件事情要做。本教程的實例app專為42mm的Apple Watch開發的,所以你需要確保正確設置了模擬器,否則界面元素看起來會有點小。對於一個現實app,需要確保界面能很好運行在兩種大小的手表上,但這在本教程的范圍之外。
在Xcode中,選擇Window\Devices打開設備管理器,點擊右下角的 + 圖標.在彈出的對話框中,命名模擬器為iPhone 6 - 42mm,設置設備類型為iPhone 6,修改配對的Apple watch為Apple Watch - 42mm (WatchOS 2.0)然後點擊Create:
關閉設備管理器,選擇Watch Scheme,然後選中新的模擬器:
編譯運行。一段模擬器啟動完成你會看到下面界面:
注意:如果收到一條錯誤消息,說明安裝失敗,然後你可以再次嘗試使用Xcode,或者在手表模擬器上手動安裝app。為此,打開iOS模擬器中的手表app,點擊AirAber,在Apple Watch彈出我們的app。一旦這麼做了,返回手表模擬器,按Shift + Ctrl + H導航到主界面, 然後點擊AirAber圖片來啟動手表app。
恭喜!你已經完成WatchKit初始界面,並使用真實的數據使它很好運行在手表模擬器上。
稍後會做什麼?
下面是這個系列教程完整示例項目。
在這個練習中你已經學會了如何往現有的iOS app中添加手表app,如何創建一個界面控制器和使用嵌套組構造一個非常復雜的界面,以及使用WKInterfaceController類來配合這項工作。那麼,接下來呢?
本教程系列的第二部分,你將學習所有關於表和導航WatchKit的使用。