watchOS 2 教程(四): Watch Connectivity

原文:watchOS 2 Tutorial Part 3: Animation

歡迎回到 watchOS 2 系列教程!

開始

打開 Watch\Interface.storyboard,從對象庫拖動一個 Interface Controller 到 storyboard 畫板中颈嚼。選中控制器纱扭,打開屬性檢查器做如下修改:

  • 設置 Identifier 為 BoardingPass;
  • 設置 Insets 為 Custom;
  • 設置 Top inset 為 6。

因為這個界面非常像 check-in 界面,設計界面有時候有些重復的工作拜银,這時候你要靈活一點牌废。

在文檔大綱中點開 CheckIn Scene,選擇那個包括起點和終點標簽的組,之后 Edit\Copy:

點擊 storyboard 中那個新的控制器的任何地方,選擇 Edit\Paste。這個只在直接往控制器里面粘貼時候有用,而往文檔大綱中粘貼沒有用,但是我也不知道為什么祥绞。

新的控制器應該是這樣:

下一步,從對象庫拖動一個 Image 放到新的控制器中,確保它與你剛才粘貼的組同級,而不是子節(jié)點:

image 控件有兩個目的;最初它顯示動畫圖片序列來告訴用戶發(fā)生什么事情鸭限,之后當手表從手機獲取到登機牌蜕径,image 會顯示它。

下載壓縮文件,解壓縮文件败京,然后拖動文件夾到 Watch\Assets.xcassets 目錄中兜喻。

確保拖動的是文件夾而不是其中的文件。這會在 asset catalog 中創(chuàng)建一個新的叫 Activity 的組喧枷,它包含一些圖片集合:

當你正在從配對的手機中請求登機牌的時候虹统,用這個圖片序列顯示不確定進度指示器。

重新打開 Watch\Interface.storyboard 然后選擇之前那個 image隧甚。使用你的老朋友屬性檢查器做如下修改:

  • 設置 Image 為 Activity车荔。自動補全有可能會建議例如 Activity1,所以確保你輸入的是 Activity;
  • 設置 Animate 為 Yes;
  • 設置 Duration 為1戚扳;
  • 選中 Animate on Load;
  • 設置 Horizontal alignment 為 Center;
  • 設置 Vertical alignment 為 Center;
  • 設置 Width 為 Fixed,值為66忧便;
  • 設置 Height 為 Fixed,值為66;

當修改完成珠增,你的屬性檢查器應該像這樣:

控制器應該像這樣:

可以看到 Image 的預覽圖片是一個又大又模糊的問題標記,不要擔心超歌;因為沒有叫 Activity 的圖片,所以 IB 不能實時預覽動畫圖片-但是請相信我蒂教,運行時就沒這問題了巍举。

設計完登機牌界面。現(xiàn)在創(chuàng)建 WKInterfaceController 的子類來做后續(xù)的工作凝垛。

創(chuàng)建控制器

在項目導航中右擊 Watch Extension 組懊悯,選擇 New File...。當對話框彈出來后選擇 watchOS\Source\WatchKit Class 然后點擊 Next梦皮。命名新的類為 BoardingPassInterfaceController,確保它是 WKInterfaceController 的子類并且語言設置為 Swift:

點擊 Next,之后 Create炭分。

當新的文件在代碼編輯器中打開了,刪除三個空的方法剑肯,只剩下重要代碼和類定義捧毛。

之后,在類的頂部添加如下 outlets:

@IBOutlet var originLabel: WKInterfaceLabel!
@IBOutlet var destinationLabel: WKInterfaceLabel!
@IBOutlet var boardingPassImage: WKInterfaceImage!

這里僅僅為剛才創(chuàng)建的圖片控件和兩個標簽增加連線让网。只要一瞬間你就能連接他們呀忧。

在連線下面增加如下代碼:

var flight: Flight? {
  didSet {
    if let flight = flight {
      originLabel.setText(flight.origin)
      destinationLabel.setText(flight.destination)
    }
  }
}

這又是我們的老朋友 flight 和它的屬性觀察器! 雖然你知道即將發(fā)生什么寂祥,但是讓我們來回顧一下荐虐,你添加了一個可選的 Flight 類型屬性七兜,包括一個屬性觀察器丸凭。當觀察器觸發(fā),嘗試解包 flight腕铸,當解包成功使用 flight 來配置兩個標簽惜犀。

現(xiàn)在僅僅需要在控制器第一次打開的時候設置 flight 屬性。添加如下代碼到 BoardingPassInterfaceController:

override func awakeWithContext(context: AnyObject?) {
  super.awakeWithContext(context)
  if let flight = context as? Flight { self.flight = flight }
}

另一個老朋友狠裹;嘗試解包轉換 context 為 Flight 對象虽界!如果轉換成功使用它來設置 self.flight,相應的觸發(fā)屬性觀察器來配置界面。

我保證這就是練習的樣板代碼涛菠。:]

現(xiàn)在莉御,打開 Watch\Interface.storyboard 選擇登機牌控制器。在 Identity Inspector 中俗冻,修改 Custom Class\Class 為 BoardingPassInterfaceController:

在文檔大綱中右擊 BoardingPass 打開 outlets 和 actions 彈出框礁叔。連接 boardingPassImage 到 image:

最后,連接 destinationLabel 到 文本為 SFO 的標簽迄薄,連接 originLabel 到文字是 MAN 的標簽琅关。

當完成這些操作,是時候更新 ScheduleInterfaceController 代碼讥蔽, 一旦用戶登記了就打開登機牌界面涣易。

打開登機牌界面

打開 ScheduleInterfaceController.swift 找到 table(_:didSelectRowAtIndex:)画机。替換這句代碼:

let controllers = ["Flight", "CheckIn"]

為下面這句代碼:

let controllers = flight.checkedIn ? ["Flight", "BoardingPass"] : ["Flight", "CheckIn"]

這里僅僅判斷用戶是否登記過選中的航班,如果登記過就顯示航班詳情和登機牌界面新症。如果沒有步氏,代替顯示航班詳情和登記界面。

編譯運行徒爹。點擊第一個航班戳护,往左清掃,點擊 Check In瀑焦。再次點擊相同的航班腌且,往左清掃,你會看到登機牌界面榛瓮,顯示不確定進度指示器:

是時候深入學習新的 Watch Connectivity 框架并且使用它請求真實的登機牌數(shù)據(jù)铺董。

請求登機牌

打開 BoardingPassInterfaceController.swift 導入 Watch Connectivity 框架:

import WatchConnecivity

下一步,在上面定義的 flight 的下面添加如下屬性:

var session: WCSession? {
  didSet {
    if let session = session {
      session.delegate = self
      session.activateSession()
    }
  }
}

這里添加一個新的類型為 WCSession 的可選屬性禀晓。在手表和手機兩個設備間的所有連接操作都是由它處理的精续;你自己并不需要實例化這個類,而是使用框架提供的單例粹懒。你已經(jīng)添加屬性觀察器了重付,當它觸發(fā)了,嘗試解包 session凫乖。當解包成功設置 session 的代理确垫,之后激活它。

即使你不實現(xiàn)類的任何代理方法帽芽,你任然需要在激活前設置 session 的代理删掀,不然情況會變得未知。

Xcode 可能會警告 BoardingPassInterfaceController 沒有遵循 WCSessionDelegate 協(xié)議导街,所以在 BoardingPassInterfaceController.swift 的底部添加如下空的擴展:

extension BoardingPassInterfaceController: WCSessionDelegate {
 
}

下一步披泪,往 BoardingPassInterfaceController 添加如下幫助方法:

private func showBoardingPass() {
  boardingPassImage.stopAnimating()
  boardingPassImage.setWidth(120)
  boardingPassImage.setHeight(120)
  boardingPassImage.setImage(flight?.boardingPass)
}

它會在兩處調用 - 如果航班已經(jīng)有登機牌了在 flight 的屬性觀察器中調用,還有另外一處是你發(fā)給你的 iPhone 的消息回調搬瑰。實現(xiàn)非常簡單-停止圖片動畫款票,增加圖片大小,之后設置顯示到登機牌的圖片泽论。

首先更新屬性觀察器艾少,往 flight 屬性觀察器中的 if 代碼塊的底部增加如下代碼

if let _ = flight.boardingPass {
  showBoardingPass()
}

只有當 flight 存在一個登機牌的時候調用 showBoardingPass() 方法。

最后一部分代碼是往 iPhone 發(fā)送請求佩厚。在 awakeWithContext(_:) 代碼的下面添加如下代碼:

override func didAppear() {
  super.didAppear()
  // 1
  if let flight = flight where flight.boardingPass == nil && WCSession.isSupported() {
    // 2
    session = WCSession.defaultSession()
    // 3
    session!.sendMessage(["reference": flight.reference], replyHandler: { (response) -> Void in
      // 4
      if let boardingPassData = response["boardingPassData"] as? NSData, boardingPass = UIImage(data: boardingPassData) {
        // 5
        flight.boardingPass = boardingPass
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
          self.showBoardingPass()
        })
      }
    }, errorHandler: { (error) -> Void in
      // 6
      print(error)
    })
  }
}

下面一步步講解以上代碼怎么回事:

  1. 假如存在有效航班姆钉,沒有登機牌,并且支持 Watch Connecivity,會繼續(xù)進入發(fā)送消息的模塊潮瓶。在嘗試與配對的手機做任何連接前你應該經(jīng)常檢查是否支持 Watch Connectivity陶冷。
  2. 設置 session 值為默認的 WCSession 單例。這會相應的觸發(fā)屬性觀察器毯辅,在激活 session 之前 設置它的代理埂伦。
  3. 往配對的 iPhone app 發(fā)送消息。一個包括航班信息的字典被轉發(fā)到 iPhone app思恐,并且提供回調和錯誤處理沾谜。
  4. iPhone app 處理接收的消息然后返回數(shù)據(jù)給手表端。手表端從返回數(shù)據(jù)中提取登機牌的圖片信息來創(chuàng)建一個 UIImage 對象胀莹。
  5. 如果操作成功了基跑,設置 UIImage 為航班登機牌的圖片,之后回到主線程調用 showBoardingPass() 來顯示給用戶描焰∠狈瘢回調和錯誤處理是在后臺線程中執(zhí)行,所以如果你需要像現(xiàn)在這樣更新界面荆秦,確保是在主線程中更新篱竭。
  6. 如果消息發(fā)送失敗簡單的打印錯誤到命令行。

這些是手表 app 端處理〔匠瘢現(xiàn)在需要相應的更新 iPhone app 端了掺逼。

回應請求

首先,導入 Watch Connectivity 框架:

import WatchConnectivity

之后瓤介,在 window 下面添加如下代碼:

var session: WCSession? {
  didSet {
    if let session = session {
      session.delegate = self
      session.activateSession()
    }
  }
}

操作與 BoardingInterfaceController 中命名一樣吕喘。簡單的一個類型 WCSession 的可選屬性,包括屬性觀察器惑朦,當觸發(fā)了觀察器兽泄,嘗試解包 session漓概。如果解包成功設置 session 的代理并且激活它漾月。

下一步,在 AppDelegate.swift 文件中添加如下擴展:

extension AppDelegate: WCSessionDelegate {
 
  func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    if let reference = message["reference"] as? String, boardingPass = QRCode(reference) {
      replyHandler(["boardingPassData": boardingPass.PNGData])
    }
  }
 
}

這里實現(xiàn)了 WCSessionDelegate 方法負責接收消息胃珍。從手表傳過來的字典中提取航班信息梁肿,之后用 Alexander Schuch 寫的牛逼的 QRCode 庫來生成二維碼,如果生成成功,調用回調函數(shù)觅彰,傳遞圖片信息到手表 app吩蔑。

最后,設置 session填抬。添加如下代碼到application(_:didFinishLaunchingWithOptions:) 方法中:

if WCSession.isSupported() {
  session = WCSession.defaultSession()
}

這里確保支持 Watch Connectivity 烛芬,之后設置 session 為框架提供的默認的 WCSession 單例。

你現(xiàn)在能夠與 iPhone app 進行雙向對話了。

編譯運行赘娄。按照如上步驟來登記航班然后查看登機牌仆潮。這次登機牌應該等段時間之后才能出現(xiàn):

祝賀!你已經(jīng)完成了使用 Watch Connectivity 向 iPhone app 請求登機牌遣臼;棒極了性置。

下一步做什么?

這是系列教程的完整示例項目

在本教程中揍堰,你學習如何在 watch app 和配對的 iPhone app 間發(fā)送實時消息鹏浅,如何在兩個設備間傳遞圖片信息。

如果你喜歡這個系列想要更多的學習關于 watchOS 2 開發(fā)知識屏歹,來看看我們的 watchOS 2 by Tutorials 書隐砸,它會教你很多開發(fā) watchOS 2 apps 的技巧。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蝙眶,一起剝皮案震驚了整個濱河市凰萨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌械馆,老刑警劉巖胖眷,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異霹崎,居然都是意外死亡珊搀,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門尾菇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來境析,“玉大人,你說我怎么就攤上這事派诬±拖” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵默赂,是天一觀的道長沛鸵。 經(jīng)常有香客問我,道長缆八,這世上最難降的妖魔是什么曲掰? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮奈辰,結果婚禮上栏妖,老公的妹妹穿的比我還像新娘。我一直安慰自己奖恰,他們只是感情好吊趾,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布宛裕。 她就那樣靜靜地躺著,像睡著了一般论泛。 火紅的嫁衣襯著肌膚如雪续滋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天孵奶,我揣著相機與錄音疲酌,去河邊找鬼。 笑死了袁,一個胖子當著我的面吹牛朗恳,可吹牛的內容都是我干的皱蹦。 我是一名探鬼主播莉给,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼浑彰,長吁一口氣:“原來是場噩夢啊……” “哼袜硫!你這毒婦竟也來了?” 一聲冷哼從身側響起属划,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤爹梁,失蹤者是張志新(化名)和其女友劉穎搀别,沒想到半個月后怕享,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體执赡,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年函筋,在試婚紗的時候發(fā)現(xiàn)自己被綠了沙合。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡跌帐,死狀恐怖首懈,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情谨敛,我是刑警寧澤究履,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站脸狸,受9級特大地震影響最仑,放射性物質發(fā)生泄漏。R本人自食惡果不足惜肥惭,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一盯仪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜜葱,春花似錦、人聲如沸耀石。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至揭鳞,卻和暖如春炕贵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背野崇。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工称开, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乓梨。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓鳖轰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扶镀。 傳聞我的和親對象是個殘疾皇子蕴侣,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容