UITableView的使用

  • 單個(gè)分區(qū)的表格

//創(chuàng)建表格視圖
self.tableView = UITableView(frame: self.view.frame, style:.plain)
//創(chuàng)建一個(gè)重用的單元格
self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
self.view.addSubview(self.tableView!)
         
//初始化數(shù)據(jù)
let items = Observable.just([
    "文本輸入框的用法",
    "開關(guān)按鈕的用法",
    "進(jìn)度條的用法",
    "文本標(biāo)簽的用法",
    ])
         
//設(shè)置單元格數(shù)據(jù)(其實(shí)就是對(duì) cellForRowAt 的封裝)
items
    .bind(to: tableView.rx.items) { (tableView, row, element) in
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
        cell.textLabel?.text = "\(row):\(element)"
        return cell
        }
      .disposed(by: disposeBag)

// 或者拆開寫為
let bibao = items.bind(to: (tableView?.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self))!)
bibao {
    (row, element, cell) in
    cell.textLabel?.text = "\(row):\(element)"
}.disposed(by: disposeBag)
  • 單元格選中事件響應(yīng)

//獲取選中項(xiàng)的索引
tableView.rx.itemSelected.subscribe(onNext: { indexPath in
    // 取消選中,這句代碼執(zhí)行后不會(huì)觸發(fā) tableView.rx.itemDeselected和tableView.rx.modelDeselected
    self.tableView!.deselectRow(at: indexPath, animated: false)    

    print("選中項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
 
//獲取選中項(xiàng)的內(nèi)容
tableView.rx.modelSelected(String.self).subscribe(onNext: { item in
    print("選中項(xiàng)的標(biāo)題為:\(item)")
}).disposed(by: disposeBag)

// 或者
//獲取選中項(xiàng)的索引
tableView.rx.itemSelected.subscribe(onNext: { [weak self] indexPath in
    // 取消選中叙甸,這句代碼執(zhí)行后不會(huì)觸發(fā) tableView.rx.itemDeselected和tableView.rx.modelDeselected
    self.tableView!.deselectRow(at: indexPath, animated: false)    

    self?.showMessage("選中項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
 
//獲取選中項(xiàng)的內(nèi)容
tableView.rx.modelSelected(String.self).subscribe(onNext: {[weak self] item in
    self?.showMessage("選中項(xiàng)的標(biāo)題為:\(item)")
}).disposed(by: disposeBag)

// 合并
Observable.zip(tableView.rx.itemSelected, tableView.rx.modelSelected(String.self))
    .bind { [weak self] indexPath, item in
        // 取消選中秧耗,這句代碼執(zhí)行后不會(huì)觸發(fā) tableView.rx.itemDeselected和tableView.rx.modelDeselected
        self.tableView!.deselectRow(at: indexPath, animated: false) 

        self?.showMessage("選中項(xiàng)的indexPath為:\(indexPath)")
        self?.showMessage("選中項(xiàng)的標(biāo)題為:\(item)")
    }
    .disposed(by: disposeBag)
  • 單元格取消選中事件響應(yīng)

//獲取被取消選中項(xiàng)的索引
tableView.rx.itemDeselected.subscribe(onNext: { [weak self] indexPath in
    self?.showMessage("被取消選中項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
 
//獲取被取消選中項(xiàng)的內(nèi)容
tableView.rx.modelDeselected(String.self).subscribe(onNext: {[weak self] item in
    self?.showMessage("被取消選中項(xiàng)的的標(biāo)題為:\(item)")
}).disposed(by: disposeBag)

// 合并
Observable.zip(tableView.rx.itemDeselected, tableView.rx.modelDeselected(String.self))
    .bind { [weak self] indexPath, item in
        self?.showMessage("被取消選中項(xiàng)的indexPath為:\(indexPath)")
        self?.showMessage("被取消選中項(xiàng)的的標(biāo)題為:\(item)")
    }
    .disposed(by: disposeBag)
  • 編輯單元格

編輯單元格時(shí),除了刪除直接實(shí)現(xiàn)下面代碼庐完,可以實(shí)現(xiàn)左滑刪除功能钢属,但不會(huì)在左邊顯示刪除按鈕;其他的操作门躯,都必須使tableView為編輯狀態(tài)淆党,并實(shí)現(xiàn)代理方法,顯示左邊對(duì)應(yīng)的按鈕

self.tableView!.isEditing = true

func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
        return .insert
    }
  • 單元格刪除事件響應(yīng)
//獲取刪除項(xiàng)的索引
tableView.rx.itemDeleted.subscribe(onNext: { [weak self] indexPath in
    self?.showMessage("刪除項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)

//獲取刪除項(xiàng)的內(nèi)容
tableView.rx.modelDeleted(String.self).subscribe(onNext: {[weak self] item in
    self?.showMessage("刪除項(xiàng)的的標(biāo)題為:\(item)")
}).disposed(by: disposeBag)
  • 單元格移動(dòng)事件響應(yīng)
//獲取移動(dòng)項(xiàng)的索引
tableView.rx.itemMoved.subscribe(onNext: { [weak self]
    sourceIndexPath, destinationIndexPath in
    self?.showMessage("移動(dòng)項(xiàng)原來的indexPath為:\(sourceIndexPath)")
    self?.showMessage("移動(dòng)項(xiàng)現(xiàn)在的indexPath為:\(destinationIndexPath)")
}).disposed(by: disposeBag)
  • 單元格插入事件響應(yīng)
//獲取插入項(xiàng)的索引
tableView.rx.itemInserted.subscribe(onNext: { [weak self] indexPath in
    self?.showMessage("插入項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
  • 單元格尾部附件(圖標(biāo))點(diǎn)擊事件響應(yīng)
//獲取點(diǎn)擊的尾部圖標(biāo)的索引
tableView.rx.itemAccessoryButtonTapped.subscribe(onNext: { [weak self] indexPath in
    self?.showMessage("尾部項(xiàng)的indexPath為:\(indexPath)")
}).disposed(by: disposeBag)
  • RxDataSources

如果我們的 tableview 需要顯示多個(gè) section、或者更加復(fù)雜的編輯功能時(shí)染乌,可以借助 RxDataSource 這個(gè)第三方庫幫我們完成山孔。
RxDataSource 的本質(zhì)就是使用 RxSwift 對(duì) UITableView 和 UICollectionView 的數(shù)據(jù)源做了一層包裝。使用它可以大大減少我們的工作量

pod 'RxDataSources'

注意:RxDataSources 是以 section 來做為數(shù)據(jù)結(jié)構(gòu)的荷憋。所以不管我們的 tableView 是單分區(qū)還是多分區(qū)台颠,在使用 RxDataSources 的過程中,都需要返回一個(gè) section 的數(shù)組勒庄。

//初始化數(shù)據(jù)
let items = Observable.just([
            SectionModel(model: "基本控件", items: [
                "UILable的用法",
                "UIText的用法",
                "UIButton的用法"
                ]),
            SectionModel(model: "高級(jí)控件", items: [
                "UITableView的用法",
                "UICollectionViews的用法"
                ])
            ])
         
//創(chuàng)建數(shù)據(jù)源
let dataSource = RxTableViewSectionedReloadDataSource
    <SectionModel<String, String>>(configureCell: {
        (dataSource, tv, indexPath, element) in
            let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
            cell.textLabel?.text = "\(indexPath.row):\(element)"
    })

//設(shè)置分區(qū)頭標(biāo)題
dataSource.titleForHeaderInSection = { ds, index in
    return ds.sectionModels[index].model
}
        
//設(shè)置分區(qū)尾標(biāo)題
dataSource.titleForFooterInSection = { ds, index in
    return "footer"
}
         
//綁定單元格數(shù)據(jù)
items
    .bind(to: tableView.rx.items(dataSource: dataSource))
    .disposed(by: disposeBag)
  • 數(shù)據(jù)刷新

//隨機(jī)的表格數(shù)據(jù)
let randomResult = refreshButton.rx.tap.asObservable()
            .startWith(()) //加這個(gè)為了讓一開始就能自動(dòng)請(qǐng)求一次數(shù)據(jù)
            .flatMapLatest{
                // 取消請(qǐng)求takeUntil
                self.getRandomResult().takeUntil(self.cancelButton.rx.tap)
            }
            .flatMap(filterResult) //篩選數(shù)據(jù)
            .share(replay: 1)
         
//創(chuàng)建數(shù)據(jù)源
let dataSource = RxTableViewSectionedReloadDataSource
    <SectionModel<String, Int>>(configureCell: {
        (dataSource, tv, indexPath, element) in
        let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
        cell.textLabel?.text = "條目\(indexPath.row):\(element)"
        return cell
    })
         
//綁定單元格數(shù)據(jù)
randomResult
    .bind(to: tableView.rx.items(dataSource: dataSource))
    .disposed(by: disposeBag)
//過濾數(shù)據(jù)
func filterResult(data:[SectionModel<String, Int>])
            -> Observable<[SectionModel<String, Int>]> {
                return self.searchBar.rx.text.orEmpty
                    //.debounce(0.5, scheduler: MainScheduler.instance) //只有間隔超過0.5秒才發(fā)送
                    .flatMapLatest{
                        query -> Observable<[SectionModel<String, Int>]> in
                        print("正在篩選數(shù)據(jù)(條件為:\(query))")
                        //輸入條件為空串前,則直接返回原始數(shù)據(jù)
                        if query.isEmpty{
                            return Observable.just(data)
                        }
                            //輸入條件為不空,則只返回包含有該文字的數(shù)據(jù)
                        else{
                            var newData:[SectionModel<String, Int>] = []
                            for sectionModel in data {
                                let items = sectionModel.items.filter{ "\($0)".contains(query) }
                                newData.append(SectionModel(model: sectionModel.model, items: items))
                            }
                            return Observable.just(newData)
                        }
                }
        }
  • 不同類型的單元格混用

//創(chuàng)建數(shù)據(jù)源
let dataSource = RxTableViewSectionedReloadDataSource<MySection>(
    //設(shè)置單元格
    configureCell: { dataSource, tableView, indexPath, item in
        switch dataSource[indexPath] {
            case let .TitleImageSectionItem(title, image):
                let cell = tableView.dequeueReusableCell(withIdentifier: "titleImageCell",
                                                             for: indexPath)
                    (cell.viewWithTag(1) as! UILabel).text = title
                    (cell.viewWithTag(2) as! UIImageView).image = image
                    return cell
                     
            case let .TitleSwitchSectionItem(title, enabled):
                let cell = tableView.dequeueReusableCell(withIdentifier: "titleSwitchCell",
                                                             for: indexPath)
                    (cell.viewWithTag(1) as! UILabel).text = title
                    (cell.viewWithTag(2) as! UISwitch).isOn = enabled
                    return cell
                }
            },
            //設(shè)置分區(qū)頭標(biāo)題
            titleForHeaderInSection: { ds, index in
                return ds.sectionModels[index].header
            }
        )
  • 樣式修改

修改單元格高度实蔽、設(shè)置組頭組尾荡碾,這些操作RxSwift沒有封裝,所以需要用原始的代理方法來實(shí)現(xiàn)

//設(shè)置代理
tableView.rx.setDelegate(self)
            .disposed(by: disposeBag)

參考文章:Swift - RxSwift的使用詳解30(UITableView的使用1:基本用法)
Swift - RxSwift的使用詳解31(UITableView的使用2:RxDataSources)
Swift - RxSwift的使用詳解32(UITableView的使用3:刷新表格數(shù)據(jù))
Swift - RxSwift的使用詳解33(UITableView的使用4:表格數(shù)據(jù)的搜索過濾)
Swift - RxSwift的使用詳解34(UITableView的使用5:可編輯表格)
Swift - RxSwift的使用詳解35(UITableView的使用6:不同類型的單元格混用)
Swift - RxSwift的使用詳解36(UITableView的使用7:樣式修改)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末局装,一起剝皮案震驚了整個(gè)濱河市坛吁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贼邓,老刑警劉巖阶冈,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異塑径,居然都是意外死亡女坑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門统舀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匆骗,“玉大人,你說我怎么就攤上這事誉简〉锞停” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵闷串,是天一觀的道長瓮钥。 經(jīng)常有香客問我,道長烹吵,這世上最難降的妖魔是什么碉熄? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮肋拔,結(jié)果婚禮上锈津,老公的妹妹穿的比我還像新娘。我一直安慰自己凉蜂,他們只是感情好琼梆,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布性誉。 她就那樣靜靜地躺著,像睡著了一般茎杂。 火紅的嫁衣襯著肌膚如雪错览。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天蛉顽,我揣著相機(jī)與錄音蝗砾,去河邊找鬼。 笑死携冤,一個(gè)胖子當(dāng)著我的面吹牛羹蚣,可吹牛的內(nèi)容都是我干的惕它。 我是一名探鬼主播耘纱,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼殴玛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了翘地?” 一聲冷哼從身側(cè)響起申尤,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衙耕,沒想到半個(gè)月后昧穿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡橙喘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年时鸵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厅瞎。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饰潜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出和簸,到底是詐尸還是另有隱情彭雾,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布锁保,位于F島的核電站薯酝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏爽柒。R本人自食惡果不足惜吴菠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望霉赡。 院中可真熱鬧橄务,春花似錦幔托、人聲如沸穴亏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嗓化。三九已至棠涮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刺覆,已是汗流浹背严肪。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谦屑,地道東北人驳糯。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像氢橙,于是被迫代替她去往敵國和親酝枢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

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

  • 1悍手、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,988評(píng)論 3 119
  • 這個(gè)星期六帘睦,我又回媽媽的老家了。 回到爺爺家后坦康,我發(fā)現(xiàn)四爺和舅舅都在爺爺家竣付,他們正在蓋一個(gè)豬圈...
    在水一方_7228閱讀 72評(píng)論 0 0
  • A區(qū): 人生目標(biāo)關(guān)鍵詞:事業(yè)/健康/親子/家庭/人際/提升/時(shí)間管理 2018年目標(biāo):學(xué)習(xí)瑜伽知識(shí),及開始習(xí)練瑜伽...
    藍(lán)天白云_d7bd閱讀 87評(píng)論 0 0
  • 瑞達(dá)利奧的其中一個(gè)原則:考察影響你的那些事物的規(guī)律滞欠,從而理解其背后的因果關(guān)系古胆,學(xué)習(xí)有效應(yīng)對(duì)這些失誤的原則。 他覺得...
    我是個(gè)秀閱讀 697評(píng)論 0 0
  • 2015-04-01 今天天氣不怎么好仑撞,下雨了赤兴。 4月的第一天,便在雨的迎接中來臨了隧哮。滿世界的水花桶良,嘩啦的喧囂,都...
    逗比丁閱讀 203評(píng)論 0 1