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

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

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

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

解決済

1回答

599閲覧

info.plist内のセクション名をUITableVIewに設定したい

Risney

総合スコア148

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

0グッド

1クリップ

投稿2020/08/16 11:32

編集2020/08/17 06:16

前提・実現したいこと

info.plist内のセクション名をUITableVIewに設定する上で必要なのは以下の2つだと思っています。
・「titleForHeaderInSection」メソッドでセクション名を取得して設定する
・「cellForRowAt」メソッドでセクション毎のセルを取得して設定する

イメージ説明

理想は以下の形でTableViewが表示されること
■Section1
・Mickey(「Image」「Name」)
■Section2
・Minnie(「Image」「Name」)
・Donald(「Image」「Name」)
・Goofy(「Image」「Name」)
・Pluto(「Image」「Name」

発生している問題・エラーメッセージ

現状Arrayの中身を表示しているなので、画像の通りになっています。
イメージ説明

該当のソースコード

swift

1import UIKit 2 3class ViewController: UIViewController ,UITableViewDelegate, UITableViewDataSource{ 4 var _items:NSArray = [] 5 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 9 // Plistファイルパス 10 let path = Bundle.main.path(forResource: "DisneyCharacterList", ofType:"plist") 11 _items = NSArray(contentsOfFile:path!)! 12 //println(_items); 13 } 14 15 // 設定 16 func numberOfSectionsInTableView(tableView: UITableView) -> Int { 17 return 1 18 } 19 20 // 設定(行数) 21 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) 22 -> Int { 23 return _items.count 24 } 25 26 // 設定(セル) 27 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 28 29 let cell = tableView.dequeueReusableCell(withIdentifier: "DisneyCell", for: indexPath as IndexPath) 30 let dic = _items.object(at: indexPath.row) as! NSDictionary 31 cell.textLabel!.text = dic.value(forKey: "Name") as? String 32 let imageName = dic.value(forKey: "Image") as! String 33 cell.imageView?.image = UIImage(named: imageName) 34 return cell 35 } 36 37 //セクション数の設定 38 func numberOfSections(in tableView: UITableView) -> Int { 39 return 2 40 } 41 42 //セクション名設定 43 let sectionTitles = ["セクション1","セクション2"] 44 func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 45 { 46 return sectionTitles[section] 47 } 48 49}

AssetCatalog
イメージ説明

info.Plist
イメージ説明

DisneyCharacterListPlist

1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3<plist version="1.0"> 4<array> 5 <dict> 6 <key>SectionName</key> 7 <string>Section1</string> 8 <key>Items</key> 9 <array> 10 <dict> 11 <key>Image</key> 12 <string>0.MickeyIcon</string> 13 <key>Name</key> 14 <string>Mickey</string> 15 </dict> 16 </array> 17 </dict> 18 <dict> 19 <key>SectionName</key> 20 <string>Section2</string> 21 <key>Items</key> 22 <array> 23 <dict> 24 <key>Image</key> 25 <string>1.MinnieIcon</string> 26 <key>Name</key> 27 <string>Minnie</string> 28 </dict> 29 <dict> 30 <key>Image</key> 31 <string>2.DonaldIcon</string> 32 <key>Name</key> 33 <string>Donald</string> 34 </dict> 35 <dict> 36 <key>Image</key> 37 <string>3.GoofyIcon</string> 38 <key>Name</key> 39 <string>Goofy</string> 40 </dict> 41 <dict> 42 <key>Image</key> 43 <string>4.PlutoIcon</string> 44 <key>Name</key> 45 <string>Pluto</string> 46 </dict> 47 </array> 48 </dict> 49</array> 50</plist> 51

参考サイト

セクションとセルをViewDidload内で関数で指定する方法は検索するとよく出てくるのですが、
ネストした構造のplistから取得して表示する方法がみつからなかったです…
[iPhone] UITableView Section の設定
【Swift】複数の section がある tableView で二次元配列を使う。
【初心者向け】UITableViewのSection(セクション)の使い方
Swift4 でTableViewを使ってみる2 「セクション機能を使いこなそう」
【Objective-C】【Swift】TableViewの基本設定について
019 セクション分けしたUITableViewを作る
[swift]ネストしたDictionaryの取得

追加修正

swift

1import UIKit 2 3struct HogeItem: Decodable { 4let Name: String 5let Image: String 6} 7 8struct HogeSection: Decodable { 9let SectionName: String 10let items: [HogeItem] 11} 12 13var _items: [HogeSection] = [] 14 15class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource { 16 17override func viewDidLoad() { 18super.viewDidLoad() 19 20if let path = Bundle.main.path(forResource: "DisneyCharacterList", ofType:"plist" ) { 21let data = try! Data(contentsOf: URL(fileURLWithPath: path)) 22_items = try! PropertyListDecoder().decode([HogeSection].self, from: data) 23} 24} 25 26// 設定 27func numberOfSectionsInTableView(tableView: UITableView) -> Int { 28return _items.count 29} 30 31// 設定(行数) 32func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 33return _items[section].items.count 34} 35 36// 設定(セクションタイトル) 37func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 38return _items[section].SectionName 39} 40 41// 設定(セル) 42func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 43let item = _items[indexPath.section].items[indexPath.row] 44 45let cell = tableView.dequeueReusableCell(withIdentifier: "DisneyCell", for: indexPath as IndexPath) 46cell.textLabel?.text = item.Name 47cell.imageView?.image = UIImage(named: item.Image) 48return cell 49} 50 51//セルタップ時にセルの内容を取得する 52func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 53let item = _items[indexPath.section].items[indexPath.row] 54 55print(item.Name) 56} 57}

「キーに関連付けられた値はありません」のようなメッセージです。

error

1Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "items", intValue: nil), Swift.DecodingError.Context(codingPath: [_PlistKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"items\", intValue: nil) (\"items\").", underlyingError: nil))

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

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

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

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

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

guest

回答1

0

ベストアンサー

前回の質問の https://teratail.com/questions/284934 の追記2でも書かせていただきましたが、PropertyListDecoder を使ったデシリアライズ方法を使ってコードの見た目をスッキリさせる方法をご提案したいです。

swift

1import UIKit 2 3struct ItemData: Decodable { 4 let Name: String 5 let Image: String 6} 7 8struct ItemGroup: Decodable { 9 let SectionName: String 10 let Items: [ItemData] 11} 12 13class ViewController: UITableViewController { 14 15 var _items: [ItemGroup] = [] 16 17 override func viewDidLoad() { 18 super.viewDidLoad() 19 20 // Plistファイルパス 21 if let path = Bundle.main.path(forResource: "DisneyCharacterList", ofType:"plist" ) { 22 let data = try! Data(contentsOf: URL(fileURLWithPath: path)) 23 _items = try! PropertyListDecoder().decode([ItemGroup].self, from: data) 24 } 25 } 26 27 // MARK: - Table view data source 28 29 override func numberOfSections(in tableView: UITableView) -> Int { 30 return _items.count 31 } 32 33 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 34 return _items[section].Items.count 35 } 36 37 override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 38 return _items[section].SectionName 39 } 40 41 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 42 let item = _items[indexPath.section].Items[indexPath.row] 43 44 let cell = tableView.dequeueReusableCell(withIdentifier: "DisneyCell", for: indexPath) 45 cell.textLabel?.text = item.Name 46 cell.imageView?.image = UIImage(named: item.Image) 47 return cell 48 } 49 50 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 51 let item = _items[indexPath.section].Items[indexPath.row] 52 53 print("item: (item.Name)") 54 } 55}

ItemGroupやItemDataのプロパティ名は異なりますが、 PropertyListDecoder を使ったサンプルプロジェクトをGitHubへアップロードいたしました。 Xcode 11.6/iOS 13.6 にて動作確認をおこなっております。

投稿2020/08/16 13:22

ch3cooh

総合スコア287

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

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

Risney

2020/08/17 06:17 編集

回答ありがとうございます。 ItemGroupやItemDataのプロパティ名を自分のものに合わせ、 実装しましたがエラーが出てしまいました。 実装内容、とエラー内容は、 質問文に追記いたしました。
ch3cooh

2020/08/17 06:19

plistでは Items になっているのに、 HogeSectionは items になっているのが原因かと思います (plistでのkeyとプロパティ名を一致させる必要があります)。 ↓ でいかがでしょうか? struct HogeSection: Decodable { let SectionName: String let Items: [HogeItem] }
Risney

2020/08/17 06:43

即レスありがとうございます!! ビルドした結果、 セクション1のヘッダーとミッキーのアイコンのみしか表示されてない状態だったので、 以下のメソッドを追加したところ無事表示されました! func numberOfSections(in tableView: UITableView) -> Int { return 2 } ただ、理想としてはこれも数字で返すのではなく、 セクション名をカウントして返したいと考えたのですが、 下記の通りにすると、_itemsの後の「section」に対してエラーが出てしまいます。 func numberOfSections(in tableView: UITableView) -> Int { return _items[section].SectionName.count } エラー内容「Use of unresolved identifier 'section'」
ch3cooh

2020/08/17 06:52

numberOfSections(in:) はセクション(複数のアイテムをまとめたもの)の数を返しますので、以下のようにセクションの数を返却してみてはいかがでしょうか。 func numberOfSections(in tableView: UITableView) -> Int { return _items.count }
Risney

2020/08/17 07:17

カウントするものが違っていたのですね!無事にできました(っ ̯- ) 丁寧にわかりやすく教えていただき本当にありがとうございました。 今色々とswiftの勉強としてサンプルを作成中なので、 また質問させて頂くと思いますが、 その時は何卒宜しくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問