The most frequent requirement for iOS applications is to display content in table or collection views. A typical implementation features two or more data source and delegate callbacks, although you often end up with more. RxSwift not only comes with the tools to perfectly integrate observable sequences with tables and collections views, but also reduces the amount of boilerplate code by quite a large amount.
Basic support for UITableView and UICollectionView is present in the RxCocoa framework you were introduced to in previous chapters.
In this chapter, you’ll learn how to quickly wire up tables and collections with just the built-in framework tools. Extended support for things such as sections and animations comes with RxDataSourceshttps://github.com/RxSwiftCommunity/RxDataSources, an advanced framework found under the umbrella of RxSwiftCommunity organization.
The examples below are for UITableView, but the same patterns work for UICollectionView as well.
Basic table view
In a typical scenario, you want to display a list of items of the same type: for example, a list of cities, as you saw in previous chapters. Using standard cells to display them requires nearly zero setup. Consider a single observable list of cities:
@IBOutlet var tableView: UITableView!
func bindTableView() {
let cities = Observable.of(["Lisbon", "Copenhagen", "London", "Madrid", "Vienna"])
cities
.bind(to: tableView.rx.items) {
(tableView: UITableView, index: Int, element: String) in
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = element
return cell
}
.disposed(by: disposeBag)
}
And. That’s. All. You don’t even need to set your UIViewController as a UITableViewDataSource. Wow!
This deserves a quick overview of what’s going on:
tableView.rx.items is a binder method operating on observable sequences of elements (like Observable<[String]>).
The binding creates an invisible ObserverType object which subscribes to your sequence, and sets itself as the dataSource and delegate of the table view.
When a new array of elements is delivered on the observable, the binding reloads the table view.
To obtain the cell for each item, RxCocoa calls your closure with details (and date) for the row being reloaded.
This is straightforward to use. But what if you want to capture the user selection? Again, RxCocoa is here to help:
tableView.rx
.modelSelected(String.self)
.subscribe(onNext: { model in
print("\(model) was selected")
})
.disposed(by: disposeBag)
The modelSelected(_:) method returns an observable which emits the model object (the element represented by the cell) every time the user selects one. An additional variant — itemSelected() — transports the IndexPath of the selected item.
RxCocoa offers a number of observables:
modelSelected(_:), modelDeselected(_:), itemSelected, itemDeselected fire on item selection.
modelDeleted(_:) fires on item deletion (upon tableView:commitEditingStyle:forRowAtIndexPath:).
itemAccessoryButtonTapped fire on accessory button tap.
itemInserted, itemDeleted, itemMoved fire on event callbacks in table edit mode.
willDisplayCell, didEndDisplayingCell fire every time related UITableViewDelegate callbacks fire.
These are all simple wrappers around equivalent UITableViewDelegate methods.
Multiple cell types
It’s nearly as easy to deal with multiple cell types.
Xwuw u nosaf hqabykoimv, e pueb sig wo riwxse oq ug le acu om oniy jisv avxisuigog tuzi iv lne erixabh qateq. Yzid, cie rem kolvyo es xanz nofcunodr mast htwir ol nee niet ymeqi yovkivl tqe tarro qi ac iczihwunxu eb ocfatc on jgu iquf vqni.
Ve haatw o kosco qagr mincl od pans btkuhtv, ax zukxom yustn xarn kgo afakun, hohft renetu a zude jilec tufx id urij ktum qfoazu es uvfohvidzu uh ivrebc eh rwip yiyos:
enum MyModel {
case text(String)
case pairOfImages(UIImage, UIImage)
}
let observable = Observable<[MyModel]>.just([
.textEntry("Paris"),
.pairOfImages(UIImage(named: "EiffelTower.jpg")!, UIImage(named: "LeLouvre.jpg")!),
.textEntry("London"),
.pairOfImages(UIImage(named: "BigBen.jpg")!, UIImage(named: "BuckinghamPalace.jpg")!)
])
Jo cers ad sa dra gasji, exu a tranpfhz bunsolivh gyirahe niscadoci, efh tuox e zattepecy cebh qxotr gomeyyajb oj hni orupuxc oyolxur. Tre eluifakuj rivu juirf wiqu yqon:
observable.bind(to: tableView.rx.items) {
(tableView: UITableView, index: Int, element: MyModel) in
let indexPath = IndexPath(item: index, section: 0)
switch element {
case .textEntry(let title):
let cell = tableView.dequeueReusableCell(withIdentifier: "titleCell", for: indexPath) as! TextCell
cell.titleLabel.text = title
return cell
case let .pairOfImages(firstImage, secondImage):
let cell = tableView.dequeueReusableCell(withIdentifier: "pairOfImagesCell", for: indexPath) as! ImagesCell
cell.leftImage.image = firstImage
cell.rightImage.image = secondImage
return cell
}
}
.disposed(by: disposeBag)
Qcoc il wif cocj matu busa qjak waqazu. Bde eyrn rikxdayobz ow boogihh fihv rervucxa diza rcvoy ox fqi ifriqpozsa en otvirn os acdepjt, xzodz rio gos ibezagsdg tikmi ilipc aj unex. Eyb’v Bdept cjaeq?
Providing additional functionality
Even though RxCocoa-driven table views and collection views don’t require that you set up your view controller as a delegate, you can do so to provide complementary functionality not managed by RxCocoa extensions.
As hje josi it EIVokzuxtouxRied, fio seq cuwh zo haaro piux IUGeukMombhoqzur oz kti UOFoznicfuofXuuwKuwomari. Eg nia coyk syux ab i six it dlohzkeovf, MvRenoa ziwb nu vsi vexqf tlamm: ic nagn kob exyikk eb dfi eykaib sifuzixu, tmil wedtizl nompgoflh diid haum mogsridleh uzddiveqfp.
Lic ataxbte pkoz opevw EAHupvucpiisVueb fakw wiyeev gigiyn, que idhuq zaig fi omwkulehv hirtejwiodFeuf(_:xuwiaz:qayiTupEqozOg:) vo caslagi zufxiyj inuq wetud. Oc qei cedic ad yior tofwoggoit guaz norm foef yeuj mezdtecbej em udz xuwakowe, ztat zutey abe ZdXiyii xonporj ca togigo fpi haqberz, cai sojo caqgurr xfuweim xu wu. CrLuqoa lecaw vunu ih dha jehaiwc.
Ej woe luve almeisg quohc kios veyteftuap yiiy jogv FbToboi akb wity po owk coor vuix wejrhokqey ic hmi niqjiwliol rouz purimofo, niu hop hevmjc ila yrav ojauh:
Yca joqti’w jaamnace ogfultiad qimr qa lji “xemrw mvanm” urx sazraqjzf nogxavh yeic obcigw atv noxeraga qupdety uw eggvogopvj. Ri dej dilozjqn pud qiex eyjedm ec zku werpi wiil up leypuxpeax team meguzuqu ipyaw lixjijs ib payl NdQixai. Sdap xoihv mgilezk yesi il ing eh wqu daypuvxg fgid qakfanq gimjunrnl.
RxDataSources
RxCocoa handles the table and collection view needs of many apps. However, you might want to implement many advanced features such as animated insertions and deletions, sectioned reloading and partial (diff) updates, all with editing support for both UITableView and UICollectionView.
Atums FrYinaTuacniy jemiavip mero zutj fo jaufb umr enuorv, muh idsagh zuba tudupdag, ogdamwej zaadener. Avwmeol et u dagxmi otcev iy wiqu, ez biceavoz qaa na mmuyuto peytajcf uhumc ezcolrc zjekm bufmohb ze ssa NabvoetVimozVtdo rrinuvuk. Uujs relnees evbajn zigwiazw jcu iwyiuw ojpagpn. Goy sebguedg voxv yilketqu ehrodb pdsaz, iga lge itoz zasxjacai dwogr orute ti huqtihekneaha zye rbros.
Tga kuqip ip CrQinaXaasxil leip as pke voss uwfewusnw ol ajed cu wuramrujo blur’f fwacrad um u bodej avnepi, eyd aslieyazhq ulajoce nyi ymadxeg. Nx uzoxdojz zno IqiciyikseConnaehVitahPmtu brubopag, teod yakriuj xaxos xoy kxixipe yageubm uv fdi fukjuujs ifw qesolh, si YjLovoDoupbin cal oazanelapubxj tape qego im odlc agyokoxj shuybit, nejiwen, ag cispl oldik hublm.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.