gpt4 book ai didi

swift - 我如何正确地将部分中的项目与 RxDataSource swift 结合起来?

转载 作者:行者123 更新时间:2023-11-28 07:20:47 28 4
gpt4 key购买 nike

当项目在一分钟内发送时,我需要在部分中合并聊天消息。

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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com