I am working on a project and I am using RXSwift. I have a tableview and I have two different cells. Both cells are two different sizes. I tried putting in the heightForRow delegate func with an if else checking the two different cells and with a switch statement checking the two but it still displays the larger cell height for both cells only.
extension CalendarVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if workoutsTableView.cellForRow(at: indexPath) == FutureSessionCell() {
return 190
}else {
return 390
}
}
}
func bindTableViewWorkouts() {
vm.workoutForOneDay.asObservable()
.bind(to: workoutsTableView.rx.items) { (tv, row, workout) -> UITableViewCell in
if workout.createdByCoach {
let cellIdentifer = FutureSessionCell.identifier
let cell = tv.dequeueReusableCell(withIdentifier: cellIdentifer, for: IndexPath.init(row: row, section: 0)) as! FutureSessionCell
cell.initCell(userSettings: UserHandler.shared.user.settings, workout: workout, name: UserHandler.shared.user.name)
return cell
}else {
let cellIdentifer = WorkoutsCardCell.identifier
let cell = tv.dequeueReusableCell(withIdentifier: cellIdentifer, for: IndexPath.init(row: row, section: 0)) as! WorkoutsCardCell
cell.initCell(userSettings: UserHandler.shared.user.settings, workout: workout, name: UserHandler.shared.user.name)
cell.openWorkout = { [unowned self] workout in
workout.presentDetailsVC(self, homeTapBarController: self.tapBarController, retrieveWorkout: { [unowned self] newWorkout in
UserHandler.shared.user.updateWorkoutData(newWorkout: newWorkout)
self.vm.updateWorkoutsForSelectedDay(self.calendar.selectedDate ?? Date()) // need to reload tableView because we updated one existing element from inside array
}, backVC: 1)
}
return cell
}
}.disposed(by: disposeBag)
vm.workoutForOneDay.asObservable()
.bind(onNext: { newWorkouts in
self.noWorkoutsView.isHidden = !newWorkouts.isEmpty
}).disposed(by: disposeBag)
}
CodePudding user response:
Try
if let _ = workoutsTableView.cellForRow(at: indexPath) as? FutureSessionCell {
return 190
}else {
return 390
}
CodePudding user response:
I suggest you setup your cell constraints so the cells autoresize. If you must manually tell the table view the height of each cell, then I would do it this way:
workoutForOneDay
.map { Dictionary(uniqueKeysWithValues: $0.enumerated().map { (IndexPath(row: $0.offset, section: 0), $0.element.createdByCoach ? 190 : 390) }) }
.bind(to: tableView.rx.heightForRowAt)
.disposed(by: disposeBag)
In order for the above to work, you would need to follow my article on how to make an Rx Delegate Proxy. Which will produce this class (put the code here in its own file.)
extension Reactive where Base: UITableView {
var delegate: UITableViewDelegateProxy {
return UITableViewDelegateProxy.proxy(for: base)
}
var heightForRowAt: Binder<[IndexPath: CGFloat]> {
Binder(delegate) { del, value in
del.heightForRowAtRelay.accept(value)
}
}
}
class UITableViewDelegateProxy
: DelegateProxy<UITableView, UITableViewDelegate>
, DelegateProxyType
, UITableViewDelegate {
static func currentDelegate(for object: UITableView) -> UITableViewDelegate? {
object.delegate
}
static func setCurrentDelegate(_ delegate: UITableViewDelegate?, to object: UITableView) {
object.delegate = delegate
}
public static func registerKnownImplementations() {
self.register { UITableViewDelegateProxy(parentObject: $0) }
}
init(parentObject: UITableView) {
super.init(
parentObject: parentObject,
delegateProxy: UITableViewDelegateProxy.self
)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
heightForRowAtRelay.value[indexPath] ?? 44
}
fileprivate let heightForRowAtRelay = BehaviorRelay<[IndexPath: CGFloat]>(value: [:])
}