我应该如何访问有关用于使用RxSwift和MVVM填充表格视图的数组的数据
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我应该如何访问有关用于使用RxSwift和MVVM填充表格视图的数组的数据相关的知识,希望对你有一定的参考价值。
我正在尝试通过制作消息传递应用程序来学习MVVM和RxSwift,但无法找出基于上一个单元格的详细信息(如果它是表视图中的最新单元格)来设置单元格样式的最佳方法。这些用于确定它是否有尾巴并在消息上方显示日期。
当前messageHasTail()
和messageShowsDate()
函数得到一个数组,上面有所有消息。
还可以对结构进行哪些改进。
TableViewControl
let appServerClient = AppServerClient()
let conversationVM:ConversationViewModel
let messages = [Message]()
init( ) {
self.inputBar = InputBarAccessoryView()
conversationVM = ConversationViewModel(appServerClient)
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
...
bindViewModel()
conversationVM.getMessages()
}
func bindViewModel(){
conversationVM.text.asObservable()
.bind(to: inputBar.inputTextView.rx.text)
.disposed(by: disposeBag)
inputBar.inputTextView.rx.text.compactMap { $0 }
.bind(to: conversationVM.text)
.disposed(by: disposeBag)
inputBar.sendButton.rx.tap.asObservable()
.bind(to: conversationVM.submitButtonTapped)
.disposed(by: disposeBag)
conversationVM.conversationOb.bind(to: self.tableView.rx.items) { tableView, index, message in
let indexPath = IndexPath(item: index, section: 0)
guard let cell = tableView.dequeueReusableCell(withIdentifier: "messageCell", for: indexPath) as? MessageCell else {
return UITableViewCell()
}
cell.isOutgoing = self.appServerClient.currentUser.id == message.user.id
cell.hasTail = self.messageHasTail(i: index)
cell.hasDate = self.messageShowsDate(i: index)
cell.message = message
// self.animateSendMessage()
return cell
}.disposed(by: disposeBag)
}
ConversationViewModel
class ConversationViewModel {
let appServerClient:AppServerClient
// var conversation: Conversation
var conversationOb: Observable<[Message]>{
return cells.asObservable()
}
var text = BehaviorRelay<String>(value:"")
let submitButtonTapped = PublishSubject<Void>()
let cells : BehaviorRelay<[Message]>
let disposeBag = DisposeBag()
init(_ appServerClient: AppServerClient) {
cells = BehaviorRelay<[Message]>(value:[])
self.appServerClient = appServerClient
submitButtonTapped
.subscribe(
onNext: { [weak self] in
self?.postMessage()
}
)
.disposed(by: disposeBag)
}
func getMessages() {
appServerClient
.getMessages()
.subscribe(
onNext: { [weak self] messages in
//empty and error removed
self?.cells.accept(messages)
}
)
.disposed(by: disposeBag)
}
func postMessage(){
appServerClient.postMessage(text: text.value)
getMessages()
}
}
MessageCell
class MessageCell: UITableViewCell {
var hasTail = true {
didSet {
messageBubble.hasTail = self.hasTail
bottomConstraint.constant = (hasTail ? vertGapPad : 0)
}
}
var hasDate = true {
didSet {
self.dateLabel.text = Date.dateMessageString(date: message.date)
hideDateConstraint.isActive = !hasDate
topConstraint.constant = (hasDate ? vertGapPad : 0)
}
}
var message = Message() {
didSet {
messageLabel.text = message.text
}
}
var isOutgoing = true {
didSet {...
答案
我建议您使用协议进行数据处理
MessageCellProtocol
[Message
必须实现MessageCellProtocol
protocol MessageCellProtocol {
var hasTail: Bool { get }
var hasDate: Bool { get }
var message: String { get set }
var date: Date { get set }
var isOutgoing: Bool { get }
}
ViewModel
final class ConversationViewModel {
private let disposeBag = DisposeBag()
private let appServerClient: AppServerClient
// 1
let sendTrigger = PublishSubject<String>()
// 2
let getTrigger = PublishSubject<Void>()
// 3
let messages = BehaviorRelay<[Message]>(value [])
init(_ appServerClient: AppServerClient) {
self.appServerClient = appServerClient
sendTrigger
// 4
.filter { !$0.isEmpty }
// 5
.map(appServerClient.postMessage)
// 6
.bind(to: getTrigger)
.disposed(by: disposeBag)
getTrigger
// 7
.flatMap { appServerClient.getMessages() }
// 8
.observeOn(MainScheduler.instance)
// 9
.bind(to: messages)
.disposed(by: disposeBag)
}
}
- 发送消息的对象
- 获取所有消息的主题
- 消息响应中继
- 当消息不是空字符串时允许发送
- 向服务器发送消息
- 绑定到getTrigger,以便在发送后获取消息
- 获取消息的请求
- 在执行请求后将响应的队列切换到MainQueue
- 绑定消息中继
MessageCell
final class MessageCell: UITableViewCell {
private (set) var message: MessageCellProtocol!
func render(_ message: MessageCellProtocol) {
self.message = message
messageBubble.hasTail = message.hasTile
bottomConstraint.constant = (message.hasTile ? vertGapPad : 0)
self.dateLabel.text = Date.dateMessageString(date: message.date)
hideDateConstraint.isActive = !message.hasDate
topConstraint.constant = (message.hasDate ? vertGapPad : 0)
messageLabel.text = message.text
...
}
ViewController
let appServerClient = AppServerClient()
let viewModel: ConversationViewModel
let messages = BehaviorRelay<[Message]>(value [])
init() {
self.inputBar = InputBarAccessoryView()
conversationVM = ConversationViewModel(appServerClient)
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
...
setupTableView()
doBindings()
}
override func viewDidAppear() {
super.viewDidAppear()
viewModel.getTrigger.onNext(())
}
func doBindings() {
inputBar
.sendButton
.rx.tap
.withLatestFrom(inputBar.inputTextView.rx.text.orEmpty)
.bind(to: viewModel.sendTrigger)
.disposed(by: disposeBag)
viewModel.messages
.bind(to: messages)
.disposed(by: disposeBag)
}
func setupTableView() {
messages
.bind(to: tableView.rx.items) { (tv, _, message) in
guard let cell = tv.dequeueReusableCell(withIdentifier: "messageCell") as? MessageCell else { return UITableVIewCell() }
cell.render(message)
return cell
}
.disposed(by: disposeBag)
}
以上是关于我应该如何访问有关用于使用RxSwift和MVVM填充表格视图的数组的数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 MVVM 和 RxSwift 编辑/删除 UICollectionView 单元格