When applying 'the trolley problem' to driverless vehicles it is often posed that the vehicle would be in such a position where it would need to either ram through pedestrians, or drive into a wall. It is assumed that either event was assuredly result in the fatality of the pedestrians or the driver (extreme assumption given the safety inside cars and the speed the car would need to hit the wall). People can fall into the trap of forgetting how astronomically unlikely it is that such a scenario would occur. How often do you hear about the man that ran over a group of people rather than sacrifice himself? What about the other way round?
Read moreGood Practice with RxSwift & MVVM - Exposing Variables
Just a quick tip for the use of RxSwift
within an MVVM architected application. Most people likely know to do this, but it never hurts to throw it out there.
In a view model, my instinct was to set it up like so:
public protocol PeopleViewModel {
/// Drives a collection of person summaries (UITableView or UICollectionView for example).
var personViewModels: Variable<[PersonViewModel]> { get }
/// Whether or not the perople are people loaded.
var isLoading: Variable<Bool>
/// Whether there are any people.
var isEmpty: Variable<Bool>
/// Fetches people after a given index (useful for paginated responses).
func fetchPeople(after index: Int)
}
Within the view, I would do the usual stuff:
private func configure(with viewModel: PeopleViewModel) {
viewModel.personViewModels.asObservable()
.bind(to: tableView.rx.items(cellIdentifier: cellIdentifier, cellType: PersonTableViewCell.self)) { (row: Int, cellModel: UserSummaryViewModeling, cell: UserTableViewCell) in
cell.viewModel = cellModel
viewModel.fetchPeople(after: row)
}
.disposed(by: disposeBag)
/// etc…
}
However, this was poor enforcement of access control and from within the view, if I was evil, I could do something like this:
viewModel.personViewModels.value = []
All my people are gone!!!
What I really want is:
public protocol PeopleViewModel {
var personViewModels: Driver<[PersonViewModel]> { get }
var isLoading: Driver<Bool>
var isEmpty: Driver<Bool>
func fetchPeople(after index: Int)
}
The implementation of which would look like:
final class PeopleViewModelImp {
let personViewModels: Driver<[PersonViewModel]> { get }
let isLoading: Driver<Bool>
let isEmpty: Driver<Bool>
fileprivate let items = Variable([PersonViewModel]())
fileprivate let isEmptyVariable = Variable(false)
fileprivate let isLoadingVariable = Variable(false)
fileptivate let apiClient: APIClient
fileprivate let disposeBag: DisposeBag
init(apiClient: APIClient) {
personViewModels = items.asDriver()
isEmpty = isEmptyVariable.asDriver()
isLoading = isLoadingVariable.asDriver()
self.apiClient = apiClient
fetchPeople(after: 0)
}
func fetchPeople(after index: Int) {
isLoadingVariable.value = true
apiClient.fetchPeople().subscribe(onNext: { people in
let viewModels = people.map(PersonViewModelImp.init(person:))
items.value += viewModels
isEmptyVariable.value = items.value.isEmpty
isLoadingVariable.value = false
})
.disposed(by: disposeBag)
}
}
Tada!
Now, in an ideal world, the fetching of the people would not be disposed of within the actual view model. The aim is to actually keep the view model free of a DisposeBag
. For now, this is fine, and certainly an improvement over the original.
The Painful Migration to Lock-swift
Recently I migrated the use of the Lock v1 SDK to the new Lock-Swift SDK and was left wrestling with issues for days. I hope this post will help anybody also having a difficult time, and this should serve in addition to the provided Migration guide which I found to be currently lacking.
Read more
The Extents of Liberalism
My problem is that I believe Russell (the proxy for general liberalism) is in danger of losing sight of the people behind these companies he so vehemently criticises. I suppose, as an iOS developer, I am bothered most by his unreasoned dislike for Apple.
Read more