【问题标题】:Adding sections, separated by dates, to UITableView in Swift在 Swift 中向 UITableView 添加按日期分隔的部分
【发布时间】:2014-10-27 20:17:24
【问题描述】:

我是 Swift 和 iOS 编程的新手,所以您必须原谅这个可能很简单的问题。

我创建了一个 tableView,它在按下按钮时显示数组(字符串)的内容。 现在,我想将这些字符串“分组”在 tableView 部分中,按日期排序。

更详细地说:当用户点击按钮时,字符串应该插入到数组的索引 0 处,并显示在带有今天日期标题的部分中。如果数组中有早于今天日期的值,则这些值应显示在该日期的单独部分中。每个部分应对应于一天 24 小时,并显示当天添加的所有字符串。

以下是我目前所取得的一些示例代码:

var testArray[String]()
var sectionsInTable[String]()

@IBOutlet weak var testTable: UITableView!

@IBAction func saveButton(sender: AnyObject) {

testArray.insert("\(strTest)", atIndex: 0)
testTable.reloaddata()

}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return sectionsInTable.count

}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{

    return testArray.count

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")

    cell.textLabel.text = String(testArray[indexPath.row])        

    return cell
}

我真的不知道如何管理部分。希望有人能指出我正确的方向。谢谢!

【问题讨论】:

    标签: ios uitableview date swift sections


    【解决方案1】:

    我需要类似的东西,虽然Ron Fessler 的解决方案有效,但当有很多部分/行时,表格需要很长时间才能加载数据,即使在那之后也没有反应灵敏。我认为那里的主要问题是 getSectionItems 函数,因为它总是会遍历所有项目...

    我的解决方案:

    struct TableItem {
        let title: String
        let creationDate: NSDate
    }
    
    var sections = Dictionary<String, Array<TableItem>>()
    var sortedSections = [String]()
    
    @IBAction func saveButton(sender: AnyObject) {
    
        let date:String = "your date in string..."
    
        //if we don't have section for particular date, create new one, otherwise we'll just add item to existing section
        if self.sections.indexForKey(date) == nil {
            self.sections[date] = [TableItem(title: name, creationDate: date)]
        }
        else {
            self.sections[date]!.append(TableItem(title: name, creationDate: date))
        } 
    
        //we are storing our sections in dictionary, so we need to sort it 
        self.sortedSections = self.sections.keys.array.sorted(>)
        self.tableView.reloadData()
    }
    

    tableView 数据源方法:

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return sections.count
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[sortedSections[section]]!.count
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        var cell = tableView.dequeueReusableCellWithIdentifier("Cell")        
    
        let tableSection = sections[sortedSections[indexPath.section]]
        let tableItem = tableSection![indexPath.row]
    
        cell.titleLabel?.text = tableItem.title
    
        return cell
    }
    
    override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sortedSections[section]
    }
    

    【讨论】:

    • 这是一个很好的简单解决方案,很容易在现有的 TableView 上实现。非常感谢。
    • 我一直收到一个 atal 错误:当我在 tabelview 委托中使用 [section] 时,索引超出范围?
    • @Skovie 检查section 是否在return 之前的sortedSections 范围内。例如:if section &lt; sortedSections.count { return ... }
    • 是的,自从 Swift 4 发布以来,我也遇到了同样的问题。
    • 很好的答案,但键上没有数组属性:sections.keys.array.sorted(>)。我必须这样排序:self.sections.keys.sorted { $0 > $1 }
    【解决方案2】:

    我通常会使用 Core Data 和 NSFetchedResultsController 执行此操作,因为它具有获取部分的内置方法。

    但是,我将在不使用 Core Data 的情况下回答这个问题。代码有点混乱,但我们开始......

    首先,您必须创建一个同时存储日期和文本的对象。 testArray 将是这些对象的数组,而不是字符串数组。例如:

    class DateTextItem: NSObject {
        var text: String = ""
        var insertDate: NSDate = NSDate()    
    }
    
    var testArray = [DateTextItem]()
    

    然后当点击 saveButton 时,我们将创建并添加 DateTextItem 对象。如果sectionsInTable 尚不存在,我们还将其添加到该日期。

    @IBAction func saveButton(sender: AnyObject) {
        let newItem = DateTextItem()
        newItem.text = "Test \(testArray.count)"
    
        // this is for development only
        // increment the date after 2 records so we can test grouping by date
        if testArray.count >= (testArray.count/2) {
            let incrementDate = NSTimeInterval(86400*(testArray.count/2))
            newItem.insertDate = NSDate(timeIntervalSinceNow:incrementDate)
        }
    
        testArray.append(newItem)
    
        // this next bit will create a date string and check if it's in the sectionInTable
        let df = NSDateFormatter()
        df.dateFormat = "MM/dd/yyyy"
        let dateString = df.stringFromDate(newItem.insertDate)
    
        // create sections NSSet so we can use 'containsObject'
        let sections: NSSet = NSSet(array: sectionsInTable)
    
        // if sectionsInTable doesn't contain the dateString, then add it
        if !sections.containsObject(dateString) {
            sectionsInTable.append(dateString)
        }
    
        self.tableView.reloadData()
    }
    

    接下来,我创建了一个函数来获取部分中的项目,因为我们在几个地方都需要它。

    func getSectionItems(section: Int) -> [DateTextItem] {
        var sectionItems = [DateTextItem]()
    
        // loop through the testArray to get the items for this sections's date
        for item in testArray {
            let dateTextItem = item as DateTextItem
            let df = NSDateFormatter()
            df.dateFormat = "MM/dd/yyyy"
            let dateString = df.stringFromDate(dateTextItem.insertDate)
    
            // if the item's date equals the section's date then add it
            if dateString == sectionsInTable[section] as NSString {
                sectionItems.append(dateTextItem)
            }
        }
    
        return sectionItems
    }
    

    最后,这是 Table View Data Source 方法的样子

    // MARK: - Table view data source
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return sectionsInTable.count
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.getSectionItems(section).count
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        // Configure the cell...
        var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    
        // get the items in this section
        let sectionItems = self.getSectionItems(indexPath.section)
        // get the item for the row in this section
        let dateTextItem = sectionItems[indexPath.row]
    
        cell.textLabel.text = dateTextItem.text
    
        return cell
    }
    
    // print the date as the section header title
    override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sectionsInTable[section]
    }
    

    【讨论】:

    • 非常感谢!将立即尝试并告诉您它是如何工作的。
    • 每次表格滚动时 - 循环正在工作并初始化数组。我不确定这是一个很好的解决方案。您需要使用对象准备一次列表,然后使用它。
    【解决方案3】:

    您必须为每一天创建一个数组(例如称为 dayArray[])并将其添加到 sectionInTable[] 并执行类似的操作:

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    
        return sectionsInTable.count
    
    }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    
        return sectionsInTable.objectAtIndex(section).count
    
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    
        cell.textLabel.text = String(sectionInTable.objectAtIndex(indexPath.section).objectAtIndex(indexPath.row))        
    
        return cell
    }
    

    对不起,如果我犯了错误,我对 swift 不熟悉,但我认为这个想法可以提供帮助。

    【讨论】:

    • 在section中添加title的方法在哪里
    【解决方案4】:

    我实现了通用算法来整理出有一天可以识别的任何对象。我想在这种情况下会有所帮助:

    protocol DayCategorizable {
        var identifierDate: Date { get }
    }
    
    extension Array where Element: DayCategorizable {
    
        var daySorted: [Date: [Element]] {
            var result: [Date: [Element]] = [:]
            let calendar = Calendar.current
            self.forEach { item in
                let i = calendar.startOfDay(for: item.identifierDate)
                if result.keys.contains(i) {
                    result[i]?.append(item)
                } else {
                    result[i] = [item]
                }
            }
            return result
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-24
      • 1970-01-01
      • 1970-01-01
      • 2015-07-12
      • 2019-04-08
      • 1970-01-01
      相关资源
      最近更新 更多