web-dev-qa-db-ja.com

SwiftでUITableViewに日付で区切られたセクションを追加する

私は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
}

セクション部分の管理方法が本当にわかりません。うまくいけば誰かが私を正しい方向に向けることができます。ありがとう!

18
maxpetter

セクションを取得するための組み込みメソッドがあるため、通常はコアデータと NSFetchedResultsController でこれを行います。

ただし、コアデータを使用せずに質問に答えます。コードは少し厄介ですが、ここで….

まず、日付とテキストの両方を保存するオブジェクトを作成する必要があります。 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
}

最後に、テーブルビューのデータソースメソッドは次のようになります。

// 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]
}
20
Ron Fessler

私は同様のものを必要としていましたが、 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 dataSourceメソッド:

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]
}
25
Adam Bardon

汎用アルゴリズムを実装して、いつか特定できるオブジェクトを整理しました。私はそのような場合に役立つと思います:

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
    }
}

毎日の配列(たとえば、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に慣れていませんが、このアイデアは役立つと思います。

0
Vincent