- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当项目在一分钟内发送时,我需要在部分中合并聊天消息。
View 模型
.....
.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
}
.....
View Controller
....
@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
}
}
....
我的 TableView 已旋转,因为我提取的消息已恢复。我知道这是我在扫描时的错误,因为当我评论这段代码时,我的单元格以正确的方式排序,但没有按部分组合。
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
最佳答案
我认为您一次尝试做的事情太多,而且顺序错误。将工作分解成更小的工作,每个工作都可以轻松测试/验证...另外,首先按时间对您的消息进行分组,然后将它们放入您的部分。我最终得到了这个:
struct MessageItem {
let userId: String
let id: String = UUID().uuidString
let text: String
let sentDate: Date
let isIncoming: Bool
}
struct MessageGroup {
let userId: String
var text: String {
return parts.map { $0.text }.joined(separator: "\n")
}
let isIncoming: Bool
struct Part {
let id: String
let text: String
let sentDate: Date
init(_ messageSectionItem: MessageItem) {
id = messageSectionItem.id
text = messageSectionItem.text
sentDate = messageSectionItem.sentDate
}
}
var parts: [Part]
init(from item: MessageItem) {
userId = item.userId
isIncoming = item.isIncoming
parts = [Part(item)]
}
}
enum MessageSectionModel {
case incomingSection(items: [MessageGroup])
case outcomingSection(items: [MessageGroup])
}
extension ObservableType where Element == MessageItem {
func convertedToSectionModels() -> Observable<[MessageSectionModel]> {
return
scan(into: ([MessageGroup](), MessageGroup?.none), accumulator: groupByTime(messages:item:))
.map(appendingLastGroup(messages:group:))
.map(groupedByIncoming(messages:))
.map(convertedToSectionModels(messages:))
}
}
func groupByTime(messages: inout ([MessageGroup], MessageGroup?), item: MessageItem) {
if let group = messages.1 {
let lastPart = group.parts.last!
if lastPart.sentDate.timeIntervalSince(item.sentDate) > -60 && group.userId == item.userId {
messages.1!.parts.append(MessageGroup.Part(item))
}
else {
messages.0.append(group)
messages.1 = MessageGroup(from: item)
}
}
else {
messages.1 = MessageGroup(from: item)
}
}
func appendingLastGroup(messages: [MessageGroup], group: MessageGroup?) -> [MessageGroup] {
guard let group = group else { return messages }
return messages + [group]
}
func groupedByIncoming(messages: [MessageGroup]) -> [[MessageGroup]] {
return messages.reduce([[MessageGroup]]()) { result, message in
guard let last = result.last else {
return [[message]]
}
if last.last!.isIncoming == message.isIncoming {
return Array(result.dropLast()) + [last + [message]]
}
else {
return result + [[message]]
}
}
}
func convertedToSectionModels(messages: [[MessageGroup]]) -> [MessageSectionModel] {
messages.map { messages in
if messages.first!.isIncoming {
return .incomingSection(items: messages)
}
else {
return .outcomingSection(items: messages)
}
}
}
关于swift - 我如何正确地将部分中的项目与 RxDataSource swift 结合起来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58176871/
我在使用 io-ts 时遇到一些问题。我发现它确实缺乏文档,我取得的大部分进展都是通过 GitHub issues 取得的。不,我不明白 HKT,所以没有帮助。 基本上,我在其他地方创建一个类型,ty
我必须创建一个正则表达式来搜索整个文件,以找到与 Java XML 解析器的第一部分(但不是第二部分)的匹配项。这将用于防止某些 XXE 攻击。不幸的是,它确实必须是单个正则表达式,并且它确实需要搜索
我有一些简单的 Shared/_Header.cshtml 文件中的内容。 My Shared/_Layout.cshtml 通过调用插入该代码 @Html.Partial("_Header") 目前
我有一个 if-else 语句,其中: 条件 1:ID 匹配并且自动填充某些字段。然后 if 语句只填充其余字段 条件 2:ID 不匹配,所有字段均为空白。 ELSE 语句将它们全部填充 当我使条件
我正在开发一个单页滚动网站。我正在尝试实现 ScrollMagic 并固定第一部分,以便网站的其余部分滚动到固定部分的顶部。我尝试创建一个 jsfiddle 来显示问题,但我似乎无法让 jsfiddl
这是我的情况: 我想使用 Google AdWords 的转换脚本,但出于某种原因,他们代码段的 javascript 部分在我的页面上添加了一些我似乎无法摆脱的不需要的空白。 所以我正在查看的选项纯
寻找一种优雅的方式在页面上添加一次脚本,就是这样。 我有一个需要 2 个 CSS 文件和 2 个 JS 文件的部分 View 。在大多数地方,只需要其中 1 个部分 View 。但在单个页面上,我需要
我想要一个网站,该网站始终具有相同的部分,具有相同的 id 以及我想要显示的所有内容。我对 javascript 不太了解,我想知道如何删除除特定部分之外的所有内容。 最好的方法是否是只执行一个循环来
SQL 语句教程 (11) Group By 我们现在回到函数上。记得我们用 SUM 这个指令来算出所有的 Sales (营业额)吧!如果我们的需求变成是要算出每一间店 (store_name)
我试图理解部分并认为我已经明白了。基本上,这是一种将部分应用程序应用于二元运算符的方法。所以我了解所有(2*) , (+1)等例子就好了。 但是在 O'Reilly Real World Haskel
有没有办法禁止在部分中覆盖给定的关键字参数?假设我要创建函数 bar总是有 a设置为 1 .在以下代码中: from functools import partial def foo(a, b):
我有这个使用节的 OpenMP 代码 #pragma omp parallel sections num_threads(8) { printf_s("Allo fro
我正在尝试重新创建 Apple 制作的有缺陷的 CNContactPickerViewController,因此我有一个数据数组 [CNContact],我需要将其整齐地显示在 UITableView
我有一个相对布局,其中包含一些 float 在 GridView 上的 TextView 。当我在网格中选择一个项目时,布局向下移动到屏幕的尽头,只有大约 1/5 的部分是可见的。这是使用简单的翻译动
我想在我的 tableView 中有两个部分。我希望将项目添加到第 0 节,然后能够选择一行以将其从第 0 节移动到第 1 节。到目前为止,我已将这些项目添加到第 0 节,但是当它关闭时数据不会加
我正在以自由职业者的身份开发支付控制软件,但我有一些关于 mysql 的问题。 。我有一个用作日志的表,名为“Bitacora”。在表中,我有一个名为 idCliente 的列,它是自己表中一个人的
我有一个 PFQueryTableViewController,我想向 tableview 添加部分,我这样尝试: - (PFQuery *)queryForTable { PFQuery *qu
我正在尝试编写一个查询,将部分匹配项与存储的名称值进行匹配。 我的数据库如下所示 Blockquote FirstName | Middle Name | Surname --------------
我正在开发一个语音备忘录应用程序,并且正在将文件保存到表格 View 中。我希望默认文件名显示为“新文件 1”,如果使用“新文件 1”,则它会显示为“新文件 2”,依此类推。 我正在尝试使用 do-w
我有以下简单的 HTML 布局 .section1 { background: red; } .section2 { background: green; } .section3 { ba
我是一名优秀的程序员,十分优秀!