【问题标题】:Group Array to introduce sections to UITableView in Swift组数组以在 Swift 中向 UITableView 引入部分
【发布时间】:2020-01-15 14:41:09
【问题描述】:

我有以下课程:

ChatMessage: Codable {
    var id: Int?
    var sender: User?
    var message: String?
    var seen: Int?
    var tsp: Date?
}

tsp 格式如下:YYYY-MM-DD hh:mm:ss

我想对同一天发送的消息进行“分组”,最终得到如下示例中的内容:

let groupedMessages = [ [ChatMessage, ChatMessage], [ChatMessage, ChatMessage, ChatMessage] ]

我最终想在 UITableViewController 中使用 groupedMessages 来引入如下部分:

func numberOfSections(in tableView: UITableView) -> Int {
        return groupedMessages.count 
        // would be 2 int the above
    }



    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return chatMessages[section].count 
        // would be 2 for the first and 3 for the second section
    }

完成排序的最高效方式是什么? - 即,一旦要排序的聊天消息数量增加,它也能正常工作

【问题讨论】:

    标签: ios arrays swift uitableview grouping


    【解决方案1】:

    你可以试试:

    let cal = Calendar.current
    let groupedMessages = Dictionary(grouping: self.chatMessages, by: { cal.startOfDay($0.tsp) })
    let keys = groupedMessages.keys.sorted(by: { $0 > $1 })
    

    然而,这会给你一个像这样的字典:

    [
      SomeDateHere: [
        ChatMessage(id: 0, sender: User?, message: "String", seen: 1),
        ChatMessage(id: 0, sender: User?, message: "String", seen: 1)
      ],
      AnotherDateHere: [
        ChatMessage(id: 0, sender: User?, message: "String", seen: 1)
    ]
    

    然后您可以使用键返回节数:

    return keys.count
    

    并像这样获取每个字典项的消息数组:

    let key = keys[indexPath.section]
    let messages = groupedMessages[key].sorted(by: { $0.tsp > $1.tsp })
    

    或者只获取计数:

    let key = keys[indexPath.section]
    return groupedMessages[key].count
    

    【讨论】:

    • 看起来是个不错的解决方案。但是字典似乎不太适合在 UITableView 部分中使用。至少我不知道如何 / 用什么替换我的代码中的 return groupedMessages.countreturn chatMessages[section].count 以使其再次工作。如果不知道字典的键,我该怎么做?
    • 分组将为您创建密钥。然后你可以像我上面提供的例子一样使用它们。
    • 太棒了——效果很好!!!最后一个快速的问题:我调用的 api 首先返回最新的聊天消息,这是有道理的。但是当我在 cellForRowAt 中简单地将它们出队时,它会在屏幕底部显示最旧的消息 - 即完全错误的顺序。在将排序闭包提供给排序闭包之前,有没有一种快速的方法来翻转排序的字典 - 或者消息数组?非常感谢您的帮助!!!
    • 刚刚更新了我的答案,向您展示如何对每个部分中的消息进行排序。如果项目没有按照您喜欢的顺序排列,您可以通过将> 更改为< 来更改排序方式。
    • 像个迷人的人一样工作 ;-) 非常感谢您的宝贵时间和帮助!!!
    【解决方案2】:

    您可以在这里找到按日期分组数组How to group array of objects by date in swift?

    如何将它连接到 UITableView,您可以在这里找到https://www.ralfebert.de/ios-examples/uikit/uitableviewcontroller/grouping-sections/

    【讨论】:

      【解决方案3】:

      我可能会从引入一种新类型开始:

      public struct CalendarDay: Hashable {
         public let date: Date
      
         public init(date: Date = Date()) {
             self.date = Calendar.current.startOfDay(for: date)
         }
      }
      
      extension CalendarDay: Comparable {
         public static func < (lhs: CalendarDay, rhs: CalendarDay) -> Bool {
            return lhs.date < rhs.date
         }
      }
      

      然后我会扩展您的信息:

      extension ChatMessage {
          var day: CalendarDay {
             return CalendarDay(date: tsp)
          }
      }
      

      (我假设tsp 不是可选的,没有理由让它成为可选的)。

      现在,让我们定义一个部分:

      struct Section {
         var messages: [ChatMessage] = []
         let day: CalendarDay
      
         init(day: CalendarDay) {
            self.day = day
         }
      }
      

      让我们轻松分组:

      let messages: [ChatMessage] = ...
      var sections: [CalendarDay: Section] = [:]
      
      for message in messages {
         let day = message.day
         var section = sections[day] ?? Section(day: day)
         section.messages.append(day)
         sections[day] = section
      }
      
      let sectionList = Array(sections.values).sorted { $0.day < $1.day }
      

      如果您的消息最初没有排序,您可能还需要单独对每个部分中的消息进行排序。

      【讨论】:

        【解决方案4】:
        let testArray = ["2016-06-23 09:07:21", "2016-06-23 08:07:21", "2016-06-22 09:07:21", "2016-06-22 08:07:21"]
        
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = "YYYY-MM-DD hh:mm:ss"
        
                let groupDic = Dictionary(grouping: testArray) { (pendingCamera) -> DateComponents in
        
                    let date = Calendar.current.dateComponents([.day, .year, .month], from: dateFormatter.date(from: pendingCamera)!)
        
                    return date
                }
                print(groupDic)
        

        您可以使用 groupDic 并在 numberOfSections 和 titleForHeaderInSection 中返回。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-08
          相关资源
          最近更新 更多