watchOS 2 教程(二):列表

原文:watchOS 2 Tutorial Part 2: Tables

歡迎回到 watchOS 2 系列教程!

在第一部分,你通過開發(fā)第一個界面控制器,學習了 watchOS 2 開發(fā)的基礎(chǔ)知識廷蓉。

在教程的第二部分,會向你的 app 添加一個 table 來展示航班列表芋忿。

在這個過程中,你會學到:

  • 如何添加一個新的界面控制器,往控制器中添加一個 table,并且設(shè)計原型行通熄。
  • 如何創(chuàng)建 WKInterfaceController 的子類來填充這個列表,配置每一行的數(shù)據(jù),并且處理選中事件;
  • 如何模態(tài)呈現(xiàn)界面控制器和向它傳遞數(shù)據(jù)來顯示。

介紹了這些,讓我們正式開始吧!

開始

打開 Watch\Interface.storyboard,從對象庫中拖動另一個界面控制器到 storyboard 畫板中,放在已經(jīng)存在的航班控制器的左邊惕鼓。

選中新的界面控制器,打開屬性檢查器然后做如下修改:

  • 設(shè)置 Identifier 為 Schedule;
  • 設(shè)置 Title 為 Air Aber;
  • 勾選 Is Inital Controller;
  • 勾選 Display Activity Indicator When Loading

你會注意到截圖的標題是深灰色的,而不是充滿活力的粉紅色。讓我們解決它。

打開文件檢查器然后改變 Globla Tint 為 #FA114F⊙魍玻現(xiàn)在看起來更好一點了:

下一步,從對象庫中拖動一個 Table 到這個新的界面控制器中:

在文本大綱中選中 Table Row Controller:

使用屬性檢查器設(shè)置它的 Identifier 為 FlightRow夷狰。使用 identifier 作為行的類型標示來通知列表哪一行應(yīng)該被實例化,它非常重要,所以需要你去設(shè)置岭皂。

設(shè)計行界面

首先修改行提供的默認布局。從文檔大綱中選擇 table row 中的組,使用屬性檢查器設(shè)置組的 Spacing 為6沼头、Height 為 Size To Fit Content爷绘。

table row 默認有個標準、固定的高度进倍。然而,大多數(shù)時候你會希望能顯示全部添加進去的界面元素,所以總是值得使用這種方式去修改高度屬性土至。

將一個分隔線從對象庫中拖到行中。你不會真的用它去分割什么,而是向你的行里添加一點視覺上的間隔猾昆。選中分割線,使用屬性檢查器做如下修改:

  • 設(shè)置 Color 為 #FA114F;
  • 設(shè)置 Vertical alignment 為 Center;
  • 設(shè)置 Height 為 Relative to Container;
  • 設(shè)置 Adjustment 為-4陶因。

最后檢查器應(yīng)該是這樣:

現(xiàn)在是時候填充這一行了!

從對象庫中拖一個Group到到 table row 中,放在分割線的后面。選中組,在屬性檢查器中修改如下屬性:

  • 設(shè)置 Layout 為 Vertical;
  • 設(shè)置 Spacing 為0;
  • 設(shè)置 Width 為 Size To Fit Content垂蜗。

你可能注意到你經(jīng)常設(shè)置的 Spacing 屬性;它的作用僅僅是收緊組中的界面元素之間的間距讓它們在小屏幕上看起來更清晰楷扬。

拖動另一個 Group 到剛才添加的組中,做如下改變:

  • 設(shè)置 Spacing 為4;
  • 設(shè)置 Height 為 Fixed,值為32解幽。

往這個新的組中,添加一個 Label、一個 Image然后另一個 Label烘苹。這兩個標簽會顯示每個航班的起點和重點躲株。

現(xiàn)在你需要往 image 中添加圖片。下載圖片然后把它添加到 Watch\Assets.xcassets 中镣衡。這次創(chuàng)建一個新的叫做Plane的圖片,放在2x槽中:

重新打開 Watch\Interface.storyboard 然后選擇這個 image霜定。使用屬性檢查器,做如下改變:

  • 設(shè)置 Image 為 Plane;
  • 設(shè)置 Tint 為 #FA114F;
  • 設(shè)置 Vertical alignment 為 Center;
  • 設(shè)置 Width 為 Fixed,值為24;
  • 設(shè)置 Height 為 Fixed,值為20。

選擇左邊的標簽設(shè)置它的文本為 MAN廊鸥。修改它的 Font 為 System, style 為 Semibold 和20的字體大小望浩。最后設(shè)置它的 Vertical alignment 為 Center。
同樣修改右邊的標簽,但是文本修改成 SFO黍图。你的 table row 現(xiàn)在應(yīng)該是這樣:

界面元素層次結(jié)構(gòu)像下面這樣:

你已經(jīng)完成大多數(shù) table row 界面的設(shè)計;之后需要增加航班號和狀態(tài)了曾雕。

從對象庫中拖動另一個 Group 到 table row ,確保它是包含起點終點標簽的那個組的子節(jié)點:

當你繼續(xù)設(shè)計這個界面,你可以看到更多使用嵌套組與混合布局來創(chuàng)建復(fù)雜布局的例子。根本就沒自動布局的事助被。

拖動兩個 label 到新的組中剖张。再次使用屬性檢查器對最左邊的標簽做如下的改變:

  • 設(shè)置 Text 為 AA123;
  • 設(shè)置 Text Color 為 Light Gray Color;
  • 設(shè)置 Font 為 Caption 2;
  • 設(shè)置 Vertical alignment 為 Bottom。

修改右邊的標簽:

  • 設(shè)置 Text 為 On time;
  • 設(shè)置 Text Color 為 #04DE71;
  • 設(shè)置 Font 為 Caption 2;
  • 設(shè)置 Horizontal alignment 為 Right;
  • 設(shè)置 Vertical alignment 為 Bottom揩环。

做完這些改變后,最后的 table row 看起來應(yīng)該像這樣:

列表在 Interface Builder 中開發(fā)完成,是時候填充一些數(shù)據(jù)了搔弄。

填充列表

首先創(chuàng)建一個 WKInterfaceController 的子類為列表提供數(shù)據(jù)。

在項目導(dǎo)航中右擊 Watch Extension 組選擇New File...丰滑。在彈出的對話框中選擇 watchOS\Source\WatchKit Class 然后點擊Next顾犹。命名新的類為 ScheduleInterfaceController,確保它是 WKInterfaceController 的子類并且語言設(shè)置為 Swift:

點擊 Next,然后 Create。

當在代碼編輯器中打開了新創(chuàng)建的文件,刪除三個空的方法后就剩下重要的語句和類定義了褒墨。

重新打開 Watch\Interface.storyboard ,選擇新的界面控制器炫刷。在 Identity Inspector,修改 Custom Class\Class 為 ScheduleInterfaceController:

在選中界面控制器的基礎(chǔ)上,打開輔助編輯器確保它顯示的是 ScheduleInterfaceController。然后按住 Ctrl從 Table 往 ScheduleInterfaceController 里面拖拽來創(chuàng)建一個 outlet:

命名 outlet 為 flightTable,確保類型設(shè)置為 WKInterfaceTable 然后點擊 Connect郁妈。

現(xiàn)在你已經(jīng)設(shè)置好自定義的類并且為 table 創(chuàng)建了一個 outlet,是時候填充一些數(shù)據(jù)了!

關(guān)閉輔助編輯器,打開 ScheduleInterfaceController.swift,在 outlet 的下面添加如下代碼

var flights = Flight.allFlights()

這里你僅僅增加了一個 Flight 對象數(shù)組保存所有航班信息浑玛。

下一步,增加 awakeWithContext(_:) 的實現(xiàn):

override func awakeWithContext(context: AnyObject?) {
  super.awakeWithContext(context)
  flightsTable.setNumberOfRows(flights.count, withRowType: "FlightRow")
}

這段代碼通知 table 為 flights 數(shù)組中每個 flight 創(chuàng)建一個 Interface Builder 中的行實例。行的數(shù)量等于數(shù)組的大小,行的類型就是你在 storyboard 中設(shè)置的 identifier 的值噩咪。

編譯運行顾彰。你會看到列表已經(jīng)填充幾行數(shù)據(jù)了:

你應(yīng)該注意到列表中顯示的是 Interface Builder 中的占位文本。為了修復(fù)這種情況,我們通過添加 row controller 分別配置每一行的 label胃碾。

添加 Row Controller

在項目導(dǎo)航中右擊 Watch Extension 組然后選擇 New File...涨享。在出現(xiàn)的對話框中選擇 watchOS\Source\WatchKit Class 然后點擊 Next。命名新的類為 FlightRowContorller,確保這個類是 NSObject 的子類并且語言設(shè)置為 Swift 了:

點擊 Next,之后 Create仆百。

當新的文件在代碼編輯器中打開了,在類的頂部增加如下代碼:

@IBOutlet var separator: WKInterfaceSeparator!
@IBOutlet var originLabel: WKInterfaceLabel!
@IBOutlet var destinationLabel: WKInterfaceLabel!
@IBOutlet var flightNumberLabel: WKInterfaceLabel!
@IBOutlet var statusLabel: WKInterfaceLabel!
@IBOutlet var planeImage: WKInterfaceImage!

這里僅僅為每個你添加到 table row 中的 label 添加對應(yīng)的 outlet厕隧。稍后會連接它們。

下一步,在這些 outlet 下面添加如下這個屬性和對應(yīng)的屬性監(jiān)視器:

// 1
var flight: Flight? {
  // 2
  didSet {
    // 3
    if let flight = flight {
      // 4
      originLabel.setText(flight.origin)
      destinationLabel.setText(flight.destination)
      flightNumberLabel.setText(flight.number)
      // 5
      if flight.onSchedule {
        statusLabel.setText("On Time")
      } else {
        statusLabel.setText("Delayed")
        statusLabel.setTextColor(UIColor.redColor())
      }
    }
  }
}

下面一步步講解是怎么回事:

  1. 你定義了類型為 Flight 的可選屬性。記住,這個類是在 Flight.swift 中定義的,而 Flight.swift 是你在教程1中添加到 Watch Extension 中的共享代碼的一部分;
  2. 添加了一個屬性監(jiān)視器,當屬性被賦值的時候會觸發(fā);
  3. 當 flight 為 nil 的時候會提前退出吁讨。因為它是可選的,只有當 Flight 對象有效的時候才去設(shè)置標簽的屬性帖族。
  4. 使用 flight 的相關(guān)屬性去設(shè)置標簽。
  5. 如果航班被延誤了,改變標簽的文本顏色,并相應(yīng)地更新文本挡爵。

當 row controller 設(shè)置完成,現(xiàn)在需要更新 table row 來使用它。

打開 Watch\Interface.storyboard 然后在文檔大綱中選擇 FlightRow甚垦。使用 Identity Inspector,設(shè)置 Custom Class\Class 為 FlightRowController茶鹃。

下一步,在文檔大綱中右擊FlightRow:

連接 planeImage 和 table row 中的 image,separator 與 table row 中的 separator。之后進行如下連線:

  • destinationLabel: SFO
  • flightNumberLabel: AA123
  • originLabel: MAN
  • statusLabel: On time

最后一步就是更新 ScheduleInterfaceController 來向列表中每個行控制器傳遞 Flight 對象艰亮。

打開 ScheduleInterfaceController.swift 之后在 awakeWithContext(_:) 底下添加如下代碼:

for index in 0..<flightsTable.numberOfRows {
  if let controller = flightsTable.rowControllerAtIndex(index) as? FlightRowController {
    controller.flight = flights[index]
  }
}

這里使用 for 循環(huán)遍歷列表中每一行來訪問指定索引的行控制器闭翩。假如你成功設(shè)置了 controller 的 flight 屬性,會觸發(fā) didSet 監(jiān)視器并且設(shè)置 table row 中所有的標簽。

是時候看看勞動成果了迄埃。編譯運行疗韵。你會看到 table row 已經(jīng)被相關(guān)的航班信息填充了:

響應(yīng)行的選中事件

首先去重寫 WKInterfaceController 中主要負責處理 table row 選中事件方法定義。

往 ScheduleInterfaceController 中添加如下代碼:

override func table(table: WKInterfaceTable, didSelectRowAtIndex rowIndex: Int) {
  let flight = flights[rowIndex]
  presentControllerWithName("Flight", context: flight)
}

這里使用行的索引來檢索出合適的航班信息侄非。之后顯示航班詳情界面,作為 context 屬性傳遞 flight 給這個界面蕉汪。presentControllerWithName(_:context:) 方法的name參數(shù)是你在 storyboard 中設(shè)置identifier的值。

現(xiàn)在你需要更新 FlightInterfaceController 來使用 context 的值來設(shè)置它的界面逞怨。

打開 FlightInterfaceController.swift,找到 awakeWithContext(_:) 者疤。替換這句代碼:

flight = Flight.allFlights().first!

為如下代碼:

if let flight = context as? Flight { self.flight = flight }

這里嘗試轉(zhuǎn)換 context 為 Flight 對象。如果轉(zhuǎn)換成功就可以使用它來設(shè)置self.flight,這會觸發(fā)屬性監(jiān)視器來設(shè)置界面叠赦。

最后,編譯運行驹马。如果你點擊某個 table row ,你會看到航班詳情界面模態(tài)彈出,顯示你選中的航班的詳情:

恭喜!你已經(jīng)完成你的第一個列表并且使用真實數(shù)據(jù)填充它;太棒了!

總結(jié)

這里目前教程的完整實例項目

在這片教程中你學習到如何往界面控制器中添加一個列表,設(shè)計 table row 界面,創(chuàng)建一個行控制器,處理 table row 選中,顯示其他界面控制器,傳遞 contexts除秀。在這20分鐘里面做了很多事情!

如果您對本教程有任何疑問或意見糯累,請參加下面的論壇進行討論!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(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
  • 正文 為了忘掉前任篮条,我火速辦了婚禮,結(jié)果婚禮上吩抓,老公的妹妹穿的比我還像新娘涉茧。我一直安慰自己,他們只是感情好疹娶,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布伴栓。 她就那樣靜靜地躺著,像睡著了一般雨饺。 火紅的嫁衣襯著肌膚如雪钳垮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天沛膳,我揣著相機與錄音椿息,去河邊找鬼蝶棋。 笑死粟瞬,一個胖子當著我的面吹牛并闲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叹哭,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼忍宋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了风罩?” 一聲冷哼從身側(cè)響起糠排,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎超升,沒想到半個月后入宦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡室琢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年乾闰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盈滴。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡涯肩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情病苗,我是刑警寧澤疗垛,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站硫朦,受9級特大地震影響贷腕,放射性物質(zhì)發(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

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