原文:watchOS 2 Tutorial Part 3: Animation
歡迎回到 watchOS 2 系列教程!
開(kāi)始
打開(kāi) Watch\Interface.storyboard集惋,從對(duì)象庫(kù)拖動(dòng)一個(gè) Interface Controller 到 storyboard 畫(huà)板中堕油。選中控制器领突,打開(kāi)屬性檢查器做如下修改:
設(shè)置 Identifier 為 BoardingPass;
設(shè)置 Insets 為 Custom;
設(shè)置 Top inset 為 6您市。
因?yàn)檫@個(gè)界面非常像 check-in 界面挪凑,設(shè)計(jì)界面有時(shí)候有些重復(fù)的工作,這時(shí)候你要靈活一點(diǎn)夯巷。
在文檔大綱中點(diǎn)開(kāi) CheckIn Scene,選擇那個(gè)包括起點(diǎn)和終點(diǎn)標(biāo)簽的組,之后 Edit\Copy:
點(diǎn)擊 storyboard 中那個(gè)新的控制器的任何地方,選擇 Edit\Paste振亮。這個(gè)只在直接往控制器里面粘貼時(shí)候有用,而往文檔大綱中粘貼沒(méi)有用,但是我也不知道為什么。
新的控制器應(yīng)該是這樣:
下一步,從對(duì)象庫(kù)拖動(dòng)一個(gè) Image 放到新的控制器中,確保它與你剛才粘貼的組同級(jí),而不是子節(jié)點(diǎn):
image 控件有兩個(gè)目的鞭莽;最初它顯示動(dòng)畫(huà)圖片序列來(lái)告訴用戶發(fā)生什么事情坊秸,之后當(dāng)手表從手機(jī)獲取到登機(jī)牌,image 會(huì)顯示它澎怒。
下載壓縮文件,解壓縮文件褒搔,然后拖動(dòng)文件夾到 Watch\Assets.xcassets 目錄中。
確保拖動(dòng)的是文件夾而不是其中的文件喷面。這會(huì)在 asset catalog 中創(chuàng)建一個(gè)新的叫 Activity 的組星瘾,它包含一些圖片集合:
當(dāng)你正在從配對(duì)的手機(jī)中請(qǐng)求登機(jī)牌的時(shí)候,用這個(gè)圖片序列顯示不確定進(jìn)度指示器惧辈。
重新打開(kāi) Watch\Interface.storyboard 然后選擇之前那個(gè) image琳状。使用你的老朋友屬性檢查器做如下修改:
設(shè)置 Image 為 Activity。自動(dòng)補(bǔ)全有可能會(huì)建議例如 Activity1盒齿,所以確保你輸入的是 Activity;
設(shè)置 Animate 為 Yes;
設(shè)置 Duration 為1念逞;
選中 Animate on Load;
設(shè)置 Horizontal alignment 為 Center;
設(shè)置 Vertical alignment 為 Center;
設(shè)置 Width 為 Fixed,值為66;
設(shè)置 Height 為 Fixed边翁,值為66翎承;
當(dāng)修改完成,你的屬性檢查器應(yīng)該像這樣:
控制器應(yīng)該像這樣:
可以看到 Image 的預(yù)覽圖片是一個(gè)又大又模糊的問(wèn)題標(biāo)記,不要擔(dān)心符匾;因?yàn)闆](méi)有叫 Activity 的圖片叨咖,所以 IB 不能實(shí)時(shí)預(yù)覽動(dòng)畫(huà)圖片-但是請(qǐng)相信我,運(yùn)行時(shí)就沒(méi)這問(wèn)題了啊胶。
設(shè)計(jì)完登機(jī)牌界面〉楦鳎現(xiàn)在創(chuàng)建 WKInterfaceController 的子類來(lái)做后續(xù)的工作。
創(chuàng)建控制器
在項(xiàng)目導(dǎo)航中右擊 Watch Extension 組焰坪,選擇 New File...趣倾。當(dāng)對(duì)話框彈出來(lái)后選擇 watchOS\Source\WatchKit Class 然后點(diǎn)擊 Next。命名新的類為 BoardingPassInterfaceController,確保它是 WKInterfaceController 的子類并且語(yǔ)言設(shè)置為 Swift:
點(diǎn)擊 Next,之后 Create琳彩。
當(dāng)新的文件在代碼編輯器中打開(kāi)了誊酌,刪除三個(gè)空的方法,只剩下重要代碼和類定義露乏。
之后碧浊,在類的頂部添加如下 outlets:
@IBOutletvar originLabel: WKInterfaceLabel!@IBOutletvar destinationLabel: WKInterfaceLabel!@IBOutletvar boardingPassImage: WKInterfaceImage!
這里僅僅為剛才創(chuàng)建的圖片控件和兩個(gè)標(biāo)簽增加連線。只要一瞬間你就能連接他們瘟仿。
在連線下面增加如下代碼:
varflight: Flight? {? didSet {ifletflight = flight {? ? ? originLabel.setText(flight.origin)? ? ? destinationLabel.setText(flight.destination)? ? }? }}
這又是我們的老朋友 flight 和它的屬性觀察器箱锐! 雖然你知道即將發(fā)生什么,但是讓我們來(lái)回顧一下劳较,你添加了一個(gè)可選的 Flight 類型屬性驹止,包括一個(gè)屬性觀察器。當(dāng)觀察器觸發(fā)观蜗,嘗試解包 flight臊恋,當(dāng)解包成功使用 flight 來(lái)配置兩個(gè)標(biāo)簽。
現(xiàn)在僅僅需要在控制器第一次打開(kāi)的時(shí)候設(shè)置? flight 屬性墓捻。添加如下代碼到 BoardingPassInterfaceController:
override func awakeWithContext(context: AnyObject?) {super.awakeWithContext(context)ifletflight = contextas? Flight { self.flight = flight }}
另一個(gè)老朋友抖仅;嘗試解包轉(zhuǎn)換 context 為 Flight 對(duì)象!如果轉(zhuǎn)換成功使用它來(lái)設(shè)置 self.flight,相應(yīng)的觸發(fā)屬性觀察器來(lái)配置界面砖第。
我保證這就是練習(xí)的樣板代碼撤卢。:]
現(xiàn)在,打開(kāi) Watch\Interface.storyboard 選擇登機(jī)牌控制器梧兼。在 Identity Inspector 中放吩,修改 Custom Class\Class 為 BoardingPassInterfaceController:
在文檔大綱中右擊 BoardingPass 打開(kāi) outlets 和 actions 彈出框。連接 boardingPassImage 到 image:
最后羽杰,連接 destinationLabel 到 文本為 SFO 的標(biāo)簽渡紫,連接 originLabel 到文字是 MAN 的標(biāo)簽。
當(dāng)完成這些操作考赛,是時(shí)候更新 ScheduleInterfaceController 代碼腻惠, 一旦用戶登記了就打開(kāi)登機(jī)牌界面。
打開(kāi)登機(jī)牌界面
打開(kāi) ScheduleInterfaceController.swift 找到 table(_:didSelectRowAtIndex:)欲虚。替換這句代碼:
letcontrollers = ["Flight","CheckIn"]
為下面這句代碼:
letcontrollers = flight.checkedIn ? ["Flight","BoardingPass"] : ["Flight","CheckIn"]
這里僅僅判斷用戶是否登記過(guò)選中的航班集灌,如果登記過(guò)就顯示航班詳情和登機(jī)牌界面。如果沒(méi)有复哆,代替顯示航班詳情和登記界面欣喧。
編譯運(yùn)行。點(diǎn)擊第一個(gè)航班梯找,往左清掃唆阿,點(diǎn)擊 Check In。再次點(diǎn)擊相同的航班锈锤,往左清掃驯鳖,你會(huì)看到登機(jī)牌界面闲询,顯示不確定進(jìn)度指示器:
是時(shí)候深入學(xué)習(xí)新的 Watch Connectivity 框架并且使用它請(qǐng)求真實(shí)的登機(jī)牌數(shù)據(jù)。
請(qǐng)求登機(jī)牌
打開(kāi) BoardingPassInterfaceController.swift? 導(dǎo)入 Watch Connectivity 框架:
importWatchConnecivity
下一步浅辙,在上面定義的 flight 的下面添加如下屬性:
varsession: WCSession? {? didSet {ifletsession = session {? ? ? session.delegate = self? ? ? session.activateSession()? ? }? }}
這里添加一個(gè)新的類型為 WCSession 的可選屬性扭弧。在手表和手機(jī)兩個(gè)設(shè)備間的所有連接操作都是由它處理的;你自己并不需要實(shí)例化這個(gè)類记舆,而是使用框架提供的單例鸽捻。你已經(jīng)添加屬性觀察器了,當(dāng)它觸發(fā)了泽腮,嘗試解包 session御蒲。當(dāng)解包成功設(shè)置 session 的代理,之后激活它诊赊。
即使你不實(shí)現(xiàn)類的任何代理方法厚满,你任然需要在激活前設(shè)置 session 的代理,不然情況會(huì)變得未知碧磅。
Xcode 可能會(huì)警告 BoardingPassInterfaceController 沒(méi)有遵循 WCSessionDelegate 協(xié)議痰滋,所以在 BoardingPassInterfaceController.swift 的底部添加如下空的擴(kuò)展:
extensionBoardingPassInterfaceController:WCSessionDelegate{ }
下一步,往 BoardingPassInterfaceController 添加如下幫助方法:
privatefuncshowBoardingPass(){? boardingPassImage.stopAnimating()? boardingPassImage.setWidth(120)? boardingPassImage.setHeight(120)? boardingPassImage.setImage(flight?.boardingPass)}
它會(huì)在兩處調(diào)用 - 如果航班已經(jīng)有登機(jī)牌了在 flight 的屬性觀察器中調(diào)用续崖,還有另外一處是你發(fā)給你的 iPhone 的消息回調(diào)敲街。實(shí)現(xiàn)非常簡(jiǎn)單-停止圖片動(dòng)畫(huà),增加圖片大小严望,之后設(shè)置顯示到登機(jī)牌的圖片多艇。
首先更新屬性觀察器,往 flight 屬性觀察器中的 if 代碼塊的底部增加如下代碼
iflet_ = flight.boardingPass {? showBoardingPass()}
只有當(dāng) flight 存在一個(gè)登機(jī)牌的時(shí)候調(diào)用 showBoardingPass() 方法像吻。
最后一部分代碼是往 iPhone 發(fā)送請(qǐng)求峻黍。在 awakeWithContext(_:) 代碼的下面添加如下代碼:
override func didAppear() {super.didAppear()// 1iflet flight = flight where flight.boardingPass ==nil&& WCSession.isSupported() {// 2session = WCSession.defaultSession()// 3session!.sendMessage(["reference": flight.reference], replyHandler: { (response) -> Voidin// 4iflet boardingPassData = response["boardingPassData"] as?NSData, boardingPass =UIImage(data: boardingPassData) {// 5flight.boardingPass = boardingPassdispatch_async(dispatch_get_main_queue(), { () -> Voidinself.showBoardingPass()? ? ? ? })? ? ? }? ? }, errorHandler: { (error) -> Voidin// 6print(error)? ? })? }}
下面一步步講解以上代碼怎么回事:
假如存在有效航班,沒(méi)有登機(jī)牌拨匆,并且支持 Watch Connecivity姆涩,會(huì)繼續(xù)進(jìn)入發(fā)送消息的模塊。在嘗試與配對(duì)的手機(jī)做任何連接前你應(yīng)該經(jīng)常檢查是否支持 Watch Connectivity惭每。
設(shè)置 session 值為默認(rèn)的 WCSession 單例骨饿。這會(huì)相應(yīng)的觸發(fā)屬性觀察器,在激活 session 之前 設(shè)置它的代理台腥。
往配對(duì)的 iPhone app 發(fā)送消息宏赘。一個(gè)包括航班信息的字典被轉(zhuǎn)發(fā)到 iPhone app,并且提供回調(diào)和錯(cuò)誤處理黎侈。
iPhone app 處理接收的消息然后返回?cái)?shù)據(jù)給手表端察署。手表端從返回?cái)?shù)據(jù)中提取登機(jī)牌的圖片信息來(lái)創(chuàng)建一個(gè) UIImage 對(duì)象。
如果操作成功了峻汉,設(shè)置 UIImage 為航班登機(jī)牌的圖片贴汪,之后回到主線程調(diào)用 showBoardingPass() 來(lái)顯示給用戶脐往。回調(diào)和錯(cuò)誤處理是在后臺(tái)線程中執(zhí)行扳埂,所以如果你需要像現(xiàn)在這樣更新界面业簿,確保是在主線程中更新。
如果消息發(fā)送失敗簡(jiǎn)單的打印錯(cuò)誤到命令行聂喇。
這些是手表 app 端處理∠皆矗現(xiàn)在需要相應(yīng)的更新 iPhone app 端了蔚携。
回應(yīng)請(qǐng)求
首先希太,導(dǎo)入 Watch Connectivity 框架:
importWatchConnectivity
之后,在 window 下面添加如下代碼:
varsession: WCSession? {? didSet {ifletsession = session {? ? ? session.delegate = self? ? ? session.activateSession()? ? }? }}
操作與 BoardingInterfaceController 中命名一樣酝蜒。簡(jiǎn)單的一個(gè)類型 WCSession 的可選屬性誊辉,包括屬性觀察器,當(dāng)觸發(fā)了觀察器亡脑,嘗試解包 session堕澄。如果解包成功設(shè)置 session 的代理并且激活它。
下一步霉咨,在 AppDelegate.swift 文件中添加如下擴(kuò)展:
extension AppDelegate: WCSessionDelegate {? func session(session: WCSession, didReceiveMessage message: [String: AnyObject],replyHandler: ([String: AnyObject]) -> Void) {ifletreference = message["reference"]as?String, boardingPass = QRCode(reference) {? ? ? replyHandler(["boardingPassData": boardingPass.PNGData])? ? }? } }
這里實(shí)現(xiàn)了 WCSessionDelegate 方法負(fù)責(zé)接收消息蛙紫。從手表傳過(guò)來(lái)的字典中提取航班信息,之后用 Alexander Schuch 寫(xiě)的牛逼的 QRCode 庫(kù)來(lái)生成二維碼,如果生成成功途戒,調(diào)用回調(diào)函數(shù)坑傅,傳遞圖片信息到手表 app。
最后喷斋,設(shè)置 session唁毒。添加如下代碼到application(_:didFinishLaunchingWithOptions:) 方法中:
ifWCSession.isSupported() {? session = WCSession.defaultSession()}
這里確保支持 Watch Connectivity ,之后設(shè)置 session 為框架提供的默認(rèn)的 WCSession 單例星爪。
你現(xiàn)在能夠與 iPhone app 進(jìn)行雙向?qū)υ捔恕?/p>
編譯運(yùn)行浆西。按照如上步驟來(lái)登記航班然后查看登機(jī)牌。這次登機(jī)牌應(yīng)該等段時(shí)間之后才能出現(xiàn):
祝賀顽腾!你已經(jīng)完成了使用 Watch Connectivity 向 iPhone app 請(qǐng)求登機(jī)牌近零;棒極了。
下一步做什么抄肖?
這是系列教程的完整示例項(xiàng)目
在本教程中秒赤,你學(xué)習(xí)如何在 watch app 和配對(duì)的 iPhone app 間發(fā)送實(shí)時(shí)消息,如何在兩個(gè)設(shè)備間傳遞圖片信息憎瘸。
如果你喜歡這個(gè)系列想要更多的學(xué)習(xí)關(guān)于 watchOS 2 開(kāi)發(fā)知識(shí)入篮,來(lái)看看我們的 watchOS 2 by Tutorials 書(shū),它會(huì)教你很多開(kāi)發(fā) watchOS 2 apps 的技巧幌甘。