質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

616閲覧

Swift5 年で分けたTableViewのSectionのセルに月のデータを振り分けて表示したい

maplemee

総合スコア16

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2022/03/15 11:43

編集2022/03/16 00:39

やりたいこと
日記のようなアプリを作っているのですが、過去の日記を遡りたい時に以下のような「年」をセクションに、「月」をセルの中に並ばせて表示をさせたい。
イメージ説明

やったこと・わからないこと
Dictionary(grouping:)を使って日付データを「年」でグループを作ってSectionに対応するところまで出来ました。そこから「月」を自動的に振り分けようとしたのですが、良い方法が思い浮かばず、一個づつSectionとrowを指定して反映させています。
●セクションの数--numberOfRowsInSection

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch section { case 0: return 1 case 1: return 2 case 2: return 1 default: break } return 0 }

●UITableView--cellForRowAt

switch indexPath.section { case 0: let section = self.sections2[0] let date = section.month cell.textLabel?.text = dateFormatter.string(from: date) case 1: switch indexPath.row { case 0: let section = self.sections2[1] let date = section.month cell.textLabel?.text = dateFormatter.string(from: date) case 1: let section = self.sections2[2] let date = section.month cell.textLabel?.text = dateFormatter.string(from: date) default: break } case 2: let section = self.sections2[3] let date = section.month cell.textLabel?.text = dateFormatter.string(from: date) default: break }

実行画面
イメージ説明

何か良い方法があればアドバイス・回答、お待ちしております。

全体コードは以下になります。

import UIKit struct Headline { var id : Int var date : Date var title : String var text : String var image : String } private func firstDayOfMonth(date: Date) -> Date { let calendar = Calendar.current let components = calendar.dateComponents([.year], from: date) return calendar.date(from: components)! } private func firstDayOfMonth2(date: Date) -> Date { let calendar = Calendar.current let components = calendar.dateComponents([.year,.month], from: date) return calendar.date(from: components)! } struct YearSection { var month : Date var headlines : [Headline] static func group(headlines : [Headline]) -> [YearSection] { let groups = Dictionary(grouping: headlines) { headline in firstDayOfMonth(date: headline.date) } return groups.map(YearSection.init(month:headlines:)) } } struct MonthSection { var month : Date var headlines : [Headline] static func group(headlines : [Headline]) -> [MonthSection] { let groups = Dictionary(grouping: headlines) { headline in firstDayOfMonth2(date: headline.date) } return groups.map(MonthSection.init(month:headlines:)) } } private func parseDate(_ str : String) -> Date { let dateFormat = DateFormatter() dateFormat.dateFormat = "yyyy-MM-dd" return dateFormat.date(from: str)! } class StoriesTableViewController: UITableViewController { var headlines = [ Headline(id: 1, date: parseDate("2018-05-15"), title: "aaa", text: "aaa", image: "Blueberry"), Headline(id: 2, date: parseDate("2018-02-15"), title: "bbb", text: "bbb", image: "Cantaloupe"), Headline(id: 2, date: parseDate("2018-02-19"), title: "bbb", text: "bbb", image: "Cantaloupe"), Headline(id: 3, date: parseDate("2017-04-05"), title: "ccc", text: "ccc", image: "Apple"), Headline(id: 4, date: parseDate("2020-09-10"), title: "ddd", text: "ddd", image: "Banana"), ] var sections = [YearSection]() var sections2 = [MonthSection]() // MARK: - View Controller lifecycle override func viewDidLoad() { super.viewDidLoad() self.sections = YearSection.group(headlines: self.headlines) self.sections.sort { lhs, rhs in lhs.month < rhs.month } self.sections2 = MonthSection.group(headlines: self.headlines) self.sections2.sort { lhs, rhs in lhs.month < rhs.month } } // MARK: - UITableViewDataSource override func numberOfSections(in tableView: UITableView) -> Int { print(sections) print("sec2+\(sections2)") return self.sections.count } override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { let section = self.sections[section] let date = section.month let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy" return dateFormatter.string(from: date) } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch section { case 0: return 1 case 1: return 2 case 2: return 1 default: break } return 0 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) let dateFormatter = DateFormatter() dateFormatter.dateFormat = "YYYY/MM" switch indexPath.section { case 0: let section = self.sections2[0] let date = section.month cell.textLabel?.text = dateFormatter.string(from: date) case 1: switch indexPath.row { case 0: let section = self.sections2[1] let date = section.month cell.textLabel?.text = dateFormatter.string(from: date) case 1: let section = self.sections2[2] let date = section.month cell.textLabel?.text = dateFormatter.string(from: date) default: break } case 2: let section = self.sections2[3] let date = section.month cell.textLabel?.text = dateFormatter.string(from: date) default: break } return cell } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

そこから「月」を自動的に振り分けようとしたのですが、良い方法が思い浮かばず、一個づつSectionとrowを指定して反映させています。

個別に判断してしまっているところが改善できれば良いということですね。
次のような感じはどうでしょうか。

swift

1import UIKit 2 3struct Headline { 4 var id : Int 5 var date : Date 6 var title : String 7 var text : String 8 var image : String 9} 10 11private func firstDayOfMonth(date: Date) -> Date { 12 let calendar = Calendar.current 13 let components = calendar.dateComponents([.year], from: date) 14 return calendar.date(from: components)! 15} 16 17private func firstDayOfMonth2(date: Date) -> Date { 18 let calendar = Calendar.current 19 let components = calendar.dateComponents([.year,.month], from: date) 20 return calendar.date(from: components)! 21} 22 23struct YearSection { 24 25 var month : Date 26 var headlines : [Headline] 27 28 static func group(headlines : [Headline]) -> [YearSection] { 29 let groups = Dictionary(grouping: headlines) { headline in 30 firstDayOfMonth(date: headline.date) 31 } 32 return groups.map(YearSection.init(month:headlines:)) 33 } 34 35} 36 37struct MonthSection { 38 var month : Date 39 var headlines : [Headline] 40 41 static func group(headlines : [Headline]) -> [MonthSection] { 42 let groups = Dictionary(grouping: headlines) { headline in 43 firstDayOfMonth2(date: headline.date) 44 } 45 return groups.map(MonthSection.init(month:headlines:)) 46 } 47} 48 49private func parseDate(_ str : String) -> Date { 50 let dateFormat = DateFormatter() 51 dateFormat.dateFormat = "yyyy-MM-dd" 52 return dateFormat.date(from: str)! 53} 54 55class StoriesTableViewController: UITableViewController { 56 57 var headlines = [ 58 Headline(id: 1, date: parseDate("2018-05-15"), title: "aaa", text: "aaa", image: "Blueberry"), 59 Headline(id: 2, date: parseDate("2018-02-15"), title: "bbb", text: "bbb", image: "Cantaloupe"), 60 Headline(id: 2, date: parseDate("2018-02-19"), title: "bbb", text: "bbb", image: "Cantaloupe"), 61 Headline(id: 3, date: parseDate("2017-04-05"), title: "ccc", text: "ccc", image: "Apple"), 62 Headline(id: 4, date: parseDate("2020-09-10"), title: "ddd", text: "ddd", image: "Banana"), 63 ] 64 65 var sections = [YearSection]() 66 var sections2 = [MonthSection]() 67 68 // MARK: - View Controller lifecycle 69 70 override func viewDidLoad() { 71 super.viewDidLoad() 72 73 self.sections = YearSection.group(headlines: self.headlines) 74 self.sections.sort { lhs, rhs in lhs.month < rhs.month } 75 76 self.sections2 = MonthSection.group(headlines: self.headlines) 77 self.sections2.sort { lhs, rhs in lhs.month < rhs.month } 78 79 } 80 81 // MARK: - UITableViewDataSource 82 83 override func numberOfSections(in tableView: UITableView) -> Int { 84 85 print(sections) 86 87 print("sec2+\(sections2)") 88 return self.sections.count 89 90 } 91 92 override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 93 let section = self.sections[section] 94 let date = section.month 95 let dateFormatter = DateFormatter() 96 dateFormatter.dateFormat = "yyyy" 97 return dateFormatter.string(from: date) 98 } 99 100 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 101 let calendar = Calendar.current 102 let date = sections[section].month 103 let year = calendar.component(.year, from: date) 104 let rows = sections2.filter({ calendar.component(.year, from: $0.month) == year }).count 105 return rows 106 } 107 108 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 109 let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) 110 111 let dateFormatter = DateFormatter() 112 dateFormatter.dateFormat = "YYYY/MM" 113 114 let calendar = Calendar.current 115 let month = sections[indexPath.section].month 116 let year = calendar.component(.year, from: month) 117 let array = sections2.filter({ calendar.component(.year, from: $0.month) == year }) 118 119 let section = array[indexPath.row] 120 let date = section.month 121 cell.textLabel?.text = dateFormatter.string(from: date) 122 123 return cell 124 } 125 126}

sectionsとsections2の繋がりを年で判断する必要があるみたいですので、データの持ち方に改善の余地があるかもしれません。

次の記事などは(少し見ただけですが・・)シンプルそうに見えました。
https://qiita.com/BMJr/items/ca7bcf76d36acbdef75e

投稿2022/03/15 15:39

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問