IGListKit框架詳細解析(三) —— 基于IGListKit框架的更好的UICollectionViews簡單示例(二)

版本記錄

版本號 時間
V1.0 2019.01.19 星期六

前言

IGListKit這個框架可能很多人沒有聽過,它其實就是一個數據驅動的UICollectionView框架,用于構建快速靈活的列表。它由Instagram開發,接下來這幾篇我們就一起看一下這個框架。感興趣的看上面幾篇。
1. IGListKit框架詳細解析(一) —— 基本概覽(一)
2. IGListKit框架詳細解析(二) —— 基于IGListKit框架的更好的UICollectionViews簡單示例(一)

Adding Messages

JPL工程師非常高興您能夠快速完成重構,但他們確實需要與被困的宇航員建立聯系。 他們已經要求您盡快集成消息模塊ASAP

在添加任何視圖之前,首先需要數據。

打開FeedViewController.swift并在FeedViewController的頂部添加一個新屬性:

let pathfinder = Pathfinder()

PathFinder()充當消息系統,代表宇航員在火星上挖出的物理Pathfinder漫游者。

ListAdapterDataSource擴展中找到objects(for:)并修改內容以匹配以下內容:

var items: [ListDiffable] = pathfinder.messages
items += loader.entries as [ListDiffable]
return items

您可能還記得,此方法為ListAdapter提供了數據源對象。 此處的修改將pathfinder.messages添加到items以為新的控制器提供消息。

注意:您必須強制轉換entries數組以使Swift編譯器可以使用。 對象已經遵循IGListDiffable

右鍵單擊SectionControllers組以創建名為MessageSectionController的新ListSectionController子類。 將IGListKitimport添加到頂部:

import IGListKit

編譯器可以使用,你現在可以保持其余的不變。

返回FeedViewController.swift并更新ListAdapterDataSource擴展中的listAdapter(_:sectionControllerFor :),使其顯示如下:

if object is Message {
  return MessageSectionController()
} else {
  return JournalSectionController()
}

如果數據對象的類型為Message,則現在返回新的message section controller

JPL團隊希望您設置具有以下要求的MessageSectionController

  • 收到消息Message
  • 有一個15點的bottom inset
  • 返回使用MessageCell.cellSize(width:text :)方法調整大小的單個單元格。
  • 使用Message對象的textuser.name值對MessageCell進行出隊和配置以填充標簽。
  • 在所有大寫中顯示Message對象的user.name值。

試一試! 如果您需要幫助,該團隊會在下面起草一個解決方案。

import IGListKit

class MessageSectionController: ListSectionController {
  var message: Message!
  
  override init() {
    super.init()
    inset = UIEdgeInsets(top: 0, left: 0, bottom: 15, right: 0)
  }
}

// MARK: - Data Provider
extension MessageSectionController {
  override func numberOfItems() -> Int {
    return 1
  }
  
  override func sizeForItem(at index: Int) -> CGSize {
    guard let context = collectionContext else {
      return .zero
    }
    return MessageCell
      .cellSize(width: context.containerSize.width, text: message.text)
  }
  
  override func cellForItem(at index: Int) -> UICollectionViewCell {
    let cell = collectionContext?
      .dequeueReusableCell(of: MessageCell.self, for: self, at: index) 
        as! MessageCell
    cell.messageLabel.text = message.text
    cell.titleLabel.text = message.user.name.uppercased()
    return cell
  }
  
  override func didUpdate(to object: Any) {
    message = object as? Message
  }  
}

準備好后,構建并運行以查看集成到Feed中的消息!


Weather on Mars

你的宇航員需要能夠獲得當前的天氣,以便在沙塵暴等障礙物周圍航行。 JPL構建了另一個顯示當前天氣的模塊。 那里有很多信息,所以他們要求天氣只在點擊時顯示。

創建一個名為WeatherSectionController的最后一個section controller。 使用初始化程序和一些變量啟動class:

import IGListKit

class WeatherSectionController: ListSectionController {
  // 1
  var weather: Weather!
  // 2
  var expanded = false
  
  override init() {
    super.init()
    // 3
    inset = UIEdgeInsets(top: 0, left: 0, bottom: 15, right: 0)
  }
}

這段代碼的作用:

  • 1) 此section controller將在didUpdate(to :)中接收Weather對象。
  • 2) expanded是一個Bool,用于跟蹤宇航員是否擴大了天氣section。 您將其初始化為false,以便最初折疊詳細信息單元格。
  • 3) 與其他section一樣,使用15點的bottom inset

現在為WeatherSectionController添加一個擴展并重寫三個方法:

// MARK: - Data Provider
extension WeatherSectionController {
  // 1
  override func didUpdate(to object: Any) {
    weather = object as? Weather
  }

  // 2
  override func numberOfItems() -> Int {
    return expanded ? 5 : 1
  }
  
  // 3
  override func sizeForItem(at index: Int) -> CGSize {
    guard let context = collectionContext else { 
      return .zero 
    }
    let width = context.containerSize.width
    if index == 0 {
      return CGSize(width: width, height: 70)
    } else {
      return CGSize(width: width, height: 40)
    }
  }
}

下面就是工作原理:

  • 1) 在didUpdate(to :)中,保存傳遞的Weather對象。
  • 2) 如果您正在顯示擴展天氣,則numberOfItems()將返回包含不同天氣數據的五個單元格。如果未展開,則只需要一個單元格即可顯示占位符。
  • 3) 第一個單元格應該比其他單元格大一些,因為它顯示標題。您不必檢查展開expanded狀態,因為該header單元格是兩種情況下的第一個單元格。

接下來,您需要實現cellForItem(at :)來配置天氣單元格。以下是一些詳細要求:

  • 第一個單元格應為WeatherSummaryCell類型,其他單元格應為WeatherDetailCell
  • 使用cell.setExpanded(_ :)配置天氣摘要單元格。
  • 使用以下標題和詳細信息標簽配置四個不同的天氣細節單元格:
    • “Sunrise” with weather.sunrise
    • “Sunset” with weather.sunset
    • “High” with "\(weather.high) C"
    • “Low” with "\(weather.low) C"

給這個cell一個截圖,解決方案就在下面。

override func cellForItem(at index: Int) -> UICollectionViewCell {
  let cellClass: AnyClass = 
    index == 0 ? WeatherSummaryCell.self : WeatherDetailCell.self
  let cell = collectionContext!
    .dequeueReusableCell(of: cellClass, for: self, at: index)

  if let cell = cell as? WeatherSummaryCell {
    cell.setExpanded(expanded)
  } else if let cell = cell as? WeatherDetailCell {
    let title: String, detail: String
    switch index {
    case 1:
      title = "SUNRISE"
      detail = weather.sunrise
    case 2:
      title = "SUNSET"
      detail = weather.sunset
    case 3:
      title = "HIGH"
      detail = "\(weather.high) C"
    case 4:
      title = "LOW"
      detail = "\(weather.low) C"
    default:
      title = "n/a"
      detail = "n/a"
    }
    cell.titleLabel.text = title
    cell.detailLabel.text = detail
  }
  return cell
}

您需要做的最后一件事是切換展開的部分并在點擊時更新單元格。 重寫ListSectionController另一個方法:

override func didSelectItem(at index: Int) {
  collectionContext?.performBatch(animated: true, updates: { batchContext in
    self.expanded.toggle()
    batchContext.reload(self)
  }, completion: nil)
}

performBatch(animated:updates:completion :)批量處理并在單個事務中執行更新。 只要控制器中的內容或單元數發生變化,就可以使用它。 由于您使用numberOfItems()切換擴展,因此將根據expanded標志添加或刪除單元格。

返回FeedViewController.swift并在FeedViewController頂部附近添加以下內容:

let wxScanner = WxScanner()

WxScanner是天氣條件的模型對象。

接下來,更新ListAdapter DataSource擴展中的objects(for:),使其如下所示:

// 1
var items: [ListDiffable] = [wxScanner.currentWeather]
items += loader.entries as [ListDiffable]
items += pathfinder.messages as [ListDiffable]
// 2
return items.sorted { (left: Any, right: Any) -> Bool in
  guard let 
    left = left as? DateSortable, 
    let right = right as? DateSortable 
    else {
      return false
  }
  return left.date > right.date
}

您已更新數據源方法以包含currentWeather。 以下是有關此功能的詳細信息:

  • 1) 將currentWeather添加到items數組中。
  • 2) 所有數據都符合DataSortable協議,因此使用該協議對數據進行排序。 這可確保數據按時間順序顯示。

最后,更新listAdapter(_:sectionControllerFor :)以顯示如下:

if object is Message {
  return MessageSectionController()
} else if object is Weather {
  return WeatherSectionController()
} else {
  return JournalSectionController()
}

Weather對象出現時,返回WeatherSectionController

建立并再次運行。 您應該在頂部看到新的天氣對象。 嘗試點擊該部分以展開和收縮它。


Performing Updates

JPL對你的進步感到欣喜若狂!

在你工作的時候,美國宇航局局長協調了宇航員的救援行動,要求他發射并攔截另一艘船! 這將是一個復雜的發射,所以他將不得不在恰當的時間升空。

JPL工程部門通過實時聊天擴展了消息傳遞模塊,他們要求您對其進行集成。

打開FeedViewController.swift并將以下行添加到viewDidLoad()的末尾:

pathfinder.delegate = self
pathfinder.connect()

Pathfinder模塊都經過實時支持修補。 您需要做的就是連接到設備并響應委托事件。

將以下擴展添加到文件的底部:

// MARK: - PathfinderDelegate
extension FeedViewController: PathfinderDelegate {
  func pathfinderDidUpdateMessages(pathfinder: Pathfinder) {
    adapter.performUpdates(animated: true)
  }
}

FeedViewController現在符合PathfinderDelegate。 單個方法performUpdates(animated :)告訴ListAdapter向其數據源詢問新對象,然后更新UI。 它處理被刪除,更新,移動或插入的對象。

構建并運行以查看隊長的消息更新! 您所要做的就是為IGListKit添加一個方法,以確定數據源中的更改內容,并在新數據到達時為更改設置動畫:

您現在需要做的就是將最新版本傳輸給宇航員,他將回家!

后記

本篇主要簡單介紹了基于IGListKit框架的更好的UICollectionViews簡單示例,感興趣的給個贊或者關注~~~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容