我应该如何访问有关用于使用RxSwift和MVVM填充表格视图的数组的数据

问题描述 投票:0回答:1

我正在尝试通过制作消息传递应用程序来学习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 {...
swift mvvm rx-swift
1个回答
1
投票

我建议您使用协议进行数据处理

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)
    }

}
  1. 发送消息的对象
  2. 获取所有消息的主题
  3. 消息响应中继
  4. 当消息不是空字符串时允许发送
  5. 向服务器发送消息
  6. 绑定到getTrigger,以便在发送后获取消息
  7. 获取消息的请求
  8. 在执行请求后将响应的队列切换到MainQueue
  9. 绑定消息中继

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)
}
© www.soinside.com 2019 - 2024. All rights reserved.