watchOS 2 教程(四): Watch Connectivity

原文: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 的技巧幌甘。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末潮售,一起剝皮案震驚了整個(gè)濱河市痊项,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌酥诽,老刑警劉巖鞍泉,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異肮帐,居然都是意外死亡咖驮,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門训枢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)托修,“玉大人,你說(shuō)我怎么就攤上這事恒界∧廊校” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵十酣,是天一觀的道長(zhǎng)涩拙。 經(jīng)常有香客問(wèn)我,道長(zhǎng)耸采,這世上最難降的妖魔是什么兴泥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮虾宇,結(jié)果婚禮上搓彻,老公的妹妹穿的比我還像新娘。我一直安慰自己文留,他們只是感情好好唯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布障本。 她就那樣靜靜地躺著往衷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪乌妙。 梳的紋絲不亂的頭發(fā)上森书,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天靶端,我揣著相機(jī)與錄音,去河邊找鬼凛膏。 笑死杨名,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的猖毫。 我是一名探鬼主播台谍,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吁断!你這毒婦竟也來(lái)了趁蕊?” 一聲冷哼從身側(cè)響起坞生,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掷伙,沒(méi)想到半個(gè)月后是己,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡任柜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年卒废,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宙地。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摔认,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绸栅,到底是詐尸還是另有隱情级野,我是刑警寧澤页屠,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布粹胯,位于F島的核電站,受9級(jí)特大地震影響辰企,放射性物質(zhì)發(fā)生泄漏风纠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一牢贸、第九天 我趴在偏房一處隱蔽的房頂上張望竹观。 院中可真熱鬧,春花似錦潜索、人聲如沸臭增。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)誊抛。三九已至,卻和暖如春整陌,著一層夾襖步出監(jiān)牢的瞬間拗窃,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工泌辫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留随夸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓震放,卻偏偏與公主長(zhǎng)得像宾毒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子殿遂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容