実現したいこと
未経験エンジニアで、Swiftは触れ始めて1週間ほどです。
iosアプリのフロント部分を担当することになりましたが、期限が短く結局ほぼAI頼りです。
TableViewCellを使用し、ヘッダーと内容、フッダーを作成しています。
ヘッダー部分をタップすると内容部分、フッダー部分は隠れる仕様を想定しています。
また、ヘッダー部分にはタイトルと一括プレビュー用ボタンを実装し、
内容部分には、DBから取得したデータ(現在はフロント部分のみなので仮データとしてNotificationData)を加工し、以下のような表示を想定しています。
__________________
項目名 内容
項目名1 内容
:
__________________
フッダー部分に「印刷」「確認」のボタンを実装予定です。
完成予想は以下の通りです
_______________
タイトル
|一括プレビュー| ⇦タップで以降下の画面が隠れる
_______________
項目名 内容
項目名1 内容1
:
_______________
|印刷| |確認|
発生している問題・分からないこと
TableViewのセットアップでNilとなってしまいエラーが発生する
エラーメッセージ
error
1Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
該当のソースコード
NotificationViewController
1import UIKit 2 3class NotificationViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 4 5 @IBOutlet weak var tableView: UITableView! 6 @IBOutlet weak var decisionButton: UIButton! 7 @IBOutlet weak var previewButton: UIButton! 8 @IBOutlet weak var footerPrintButton: UIButton! 9 @IBOutlet weak var footerConfirmButton: UIButton! 10 11 var data: [NotificationData] = NotificationData.sampleData 12 var isSectionCollapsed: [Bool] = Array(repeating: false, count: NotificationData.sampleData.count) 13 14 override func viewDidLoad() { 15 super.viewDidLoad() 16 17 self.view.backgroundColor = .white 18 19 // TableViewのセットアップ 20 tableView.dataSource = self 21 tableView.delegate = self 22 tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") 23 24 // ボタンの初期設定 25 decisionButton.setTitle("決裁", for: .normal) 26 previewButton.setTitle("一括プレビュー", for: .normal) 27 footerPrintButton.setTitle("印刷", for: .normal) 28 footerConfirmButton.setTitle("確認", for: .normal) 29 } 30 31 // TableViewの行数を返す 32 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 33 return isSectionCollapsed[section] ? 0 : data[section].details.count 34 } 35 36 // セクションのタイトルを設定 37 func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 38 return data[section].title 39 } 40 41 // セクションのヘッダーがタップされたときに開閉を切り替える 42 func tableView(_ tableView: UITableView, didSelectHeaderView section: Int) { 43 isSectionCollapsed[section].toggle() 44 tableView.reloadSections([section], with: .automatic) 45 } 46 47 // セルの内容を設定 48 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 49 let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) 50 let detail = data[indexPath.section].details[indexPath.row] 51 cell.textLabel?.text = "\(detail.item): \(detail.content)" 52 return cell 53 } 54 55 // ボタンがタップされたときのアクション 56 @IBAction func decisionButtonTapped(_ sender: UIButton) { 57 print("決裁ボタンがタップされました") 58 } 59 60 @IBAction func previewButtonTapped(_ sender: UIButton) { 61 print("一括プレビューボタンがタップされました") 62 } 63 64 @IBAction func footerPrintButtonTapped(_ sender: UIButton) { 65 print("印刷ボタンがタップされました") 66 } 67 68 @IBAction func footerConfirmButtonTapped(_ sender: UIButton) { 69 print("確認ボタンがタップされました") 70 } 71} 72
NotificationData
1import Foundation 2 3struct NotificationData { 4 let title: String 5 let details: [(item: String, content: String)] 6 7 static let sampleData: [NotificationData] = [ 8 NotificationData( 9 title: "決裁 [827] テストフォーム(テスト0307)", 10 details: [ 11 ("申請者", "承認ユーザ 1 (41)"), 12 ("申請日", "2025/03/07(金) 14:13"), 13 ("標題", "テスト0307"), 14 ("申請項目1", ""), 15 ("申請項目2", ""), 16 ("申請項目3", ""), 17 ("申請項目4", "") 18 ] 19 ), 20 NotificationData( 21 title: "→決裁", 22 details: [ 23 ("決裁", "承認ユーザ 2 (42)"), 24 ("", "てすと0307") 25 ] 26 ) 27 ] 28} 29
NotificationCell
1import UIKit 2 3class NotificationCell: UIView { 4 5 init(data: NotificationData) { 6 super.init(frame: .zero) 7 8 let stackView = UIStackView() 9 stackView.axis = .vertical 10 stackView.spacing = 8 11 stackView.translatesAutoresizingMaskIntoConstraints = false 12 self.addSubview(stackView) 13 14 // データ加工 15 for detail in data.details { 16 let rowStack = UIStackView() 17 rowStack.axis = .horizontal 18 rowStack.spacing = 8 19 20 let itemLabel = UILabel() 21 itemLabel.text = detail.item 22 itemLabel.textColor = .blue 23 itemLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal) 24 25 let contentLabel = UILabel() 26 contentLabel.text = detail.content 27 contentLabel.textColor = .black 28 contentLabel.numberOfLines = 0 29 30 rowStack.addArrangedSubview(itemLabel) 31 rowStack.addArrangedSubview(contentLabel) 32 33 stackView.addArrangedSubview(rowStack) 34 } 35 36 // 「決裁」項目を追加(タイトルではなく項目として追加) 37 let decisionItemStack = UIStackView() 38 decisionItemStack.axis = .horizontal 39 decisionItemStack.spacing = 8 40 41 let decisionLabel = UILabel() 42 decisionLabel.text = "決裁" 43 decisionLabel.textColor = .blue 44 decisionItemStack.addArrangedSubview(decisionLabel) 45 46 stackView.addArrangedSubview(decisionItemStack) 47 48 // 点線を追加(最後の項目の下) 49 let dottedLine = UIView() 50 dottedLine.backgroundColor = .gray 51 dottedLine.translatesAutoresizingMaskIntoConstraints = false 52 self.addSubview(dottedLine) 53 54 // 点線の表示(最後の項目の下に追加) 55 NSLayoutConstraint.activate([ 56 dottedLine.heightAnchor.constraint(equalToConstant: 1), 57 dottedLine.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 15), 58 dottedLine.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -15), 59 dottedLine.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 16) 60 ]) 61 62 NSLayoutConstraint.activate([ 63 stackView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10), 64 stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 15), 65 stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -15), 66 stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10) 67 ]) 68 } 69 70 required init?(coder: NSCoder) { 71 fatalError("init(coder:) has not been implemented") 72 } 73} 74
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
同様の質問はありましたが、その回答は既に実施済みであったものの解決しませんでした。
AIから提案された確認も全て行いましたが、解決せず3日ほど経ちました。
補足
特になし

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/03/10 13:03