Мне нужно объединить сообщение чата в разделе, когда элементы отправляются в течение одной минуты.
ViewModel
.....
.scan([MessageSectionModel]()) { sectionModels, messageItem in
var models = sectionModels
if let lastSectionModel = sectionModels.last {
switch lastSectionModel {
case .incomingSection(var items):
if messageItem.0.isIncoming {
items.append(messageItem.0)
models[models.count-1] = .incomingSection(items: items)
} else {
models.append(.outcomingSection(items: [messageItem.0]))
}
case .outcomingSection(var items):
if messageItem.0.isIncoming {
models.append(.incomingSection(items: [messageItem.0]))
} else {
items.append(messageItem.0)
models[models.count-1] = .outcomingSection(items: items)
}
}
return models
}
if messageItem.0.isIncoming {
models.append(.incomingSection(items: [messageItem.0]))
} else {
models.append(.outcomingSection(items: [messageItem.0]))
}
return models
}
.....
ViewController
....
@IBOutlet private weak var messagesTableView: UITableView!
private let disposeBag = DisposeBag()
private var dataSource: RxTableViewSectionedAnimatedDataSource<MessageSectionModel>!
private let messageHeaderReuseIdentifier = String(describing: MessageHeaderView.self)
private let messageFooterReuseIdentifier = String(describing: MessageFooterView.self)
dataSource = RxTableViewSectionedAnimatedDataSource<MessageSectionModel>(
animationConfiguration: .init(insertAnimation: .none, reloadAnimation: .none, deleteAnimation: .none),
configureCell: { dataSource, tableView, indexPath, item in
switch dataSource.sectionModels[indexPath.section] {
case .incomingSection:
guard let cell = tableView.dequeueReusableCell(
withIdentifier: R.reuseIdentifier.incomingMessageTableViewCell,
for: indexPath
) else {
return UITableViewCell()
}
let isFirst = indexPath.row == dataSource[indexPath.section].items.count - 1
cell.bind(
messageText: item.text,
isFirstInSection: isFirst
)
return cell
case .userSection:
guard let cell = tableView.dequeueReusableCell(
withIdentifier: R.reuseIdentifier.outcomingMessageTableViewCell,
for: indexPath
) else {
return UITableViewCell()
}
cell.bind(
messageText: item.text,
isFirstInSection: indexPath.row == dataSource[indexPath.section].items.count - 1
)
return cell
}
})
....
Элементы сообщения
....
import Foundation
import RxDataSources
enum MessageSectionModel {
case incomingSection(items: [MessageSectionItem])
case outcomingSection(items: [MessageSectionItem])
var lastMessageDate: Date {
switch self {
case .incomingSection(let items):
return items.last?.sentDate ?? Date()
case .outcomingSection(let items):
return items.last?.sentDate ?? Date()
}
}
}
struct MessageSectionItem {
let userId: String
let id: String = UUID().uuidString
let text: String
let sentDate: Date
let isIncoming: Bool
}
extension MessageSectionItem: IdentifiableType {
var identity : String {
return id
}
}
extension MessageSectionItem: Equatable {
static func == (lhs: MessageSectionItem, rhs: MessageSectionItem) -> Bool {
return lhs.identity == rhs.identity
}
}
extension MessageSectionModel: AnimatableSectionModelType {
init(original: MessageSectionModel, items: [MessageSectionItem]) {
switch original {
case .incomingSection(let items):
self = .incomingSection(items: items)
case .outcomingSection(let items):
self = .outcomingSection(items: items)
}
}
typealias Item = MessageSectionItem
var items: [MessageSectionItem] {
switch self {
case .incomingSection(let items):
return items.map { $0 }
case .outcomingSection(let items):
return items.map { $0 }
}
}
var identity: Date {
return lastMessageDate
}
}
....
Мой вид таблицы вращается, потому что я получаю сообщения, которые возвращаются. Я понимаю, что это моя ошибка в сканировании, потому что, когда я комментирую этот код, мои ячейки сортируются правильно, но не объединяются в разделы.
if let lastSectionModel = sectionModels.last {
switch lastSectionModel {
case .incomingSection(var items):
if messageItem.0.isIncoming {
items.append(messageItem.0)
models[models.count-1] = .incomingSection(items: items)
} else {
models.append(.outcomingSection(items: [messageItem.0]))
}
case .outcomingSection(var items):
if messageItem.0.isIncoming {
models.append(.incomingSection(items: [messageItem.0]))
} else {
items.append(messageItem.0)
models[models.count-1] = .outcomingSection(items: items)
}
}
return models