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

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

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

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

Q&A

解決済

1回答

2608閲覧

swift TableViewにMPMediaQueryからデータを取得しすぎてしまう・・・

mitci

総合スコア37

Swift

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

0グッド

0クリップ

投稿2017/12/03 13:10

編集2017/12/06 03:56

###前提・実現したいこと
以下のコードで、MPMediaQueryからアーティストを取り出して、テーブルビューに入れているのですが、このように、同じアーティストを曲の数だけ繰り返してしまうのです・・・繰り返しすぎ

コードは、

swift

1func getArtistInfo() -> Array<MPMediaItem> { 2 var array = Array<MPMediaItem>() 3 let artistQuery: MPMediaQuery = MPMediaQuery.artists() 4 let artistCollections: [MPMediaItemCollection] = artistQuery.collections! 5 for artist in artistCollections { 6 let artistItems: [MPMediaItem] = artist.items 7 for artists in artistItems { 8 array.append(artists) 9 } 10 } 11 return array 12 } 13//これで取得して、 14 15 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 16 return data.count 17 } 18 19 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 20 let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "myCell") 21 cell.textLabel?.text = data[indexPath.row].artist 22 return cell 23 } 24//これでテーブルに入れています。

###試したこと
クエリ周りの記述は本を見て丸写ししたものをちょっとアレンジをしただけなので、
あまり理解が進んでいません・・・
MediaQueryが曲ごとに各.artists()やら.albums()を参照しているからなのだろうとは思うのですが、OrderedSetなどで重複を削除しようにも、どうしたらいいのか・・・

###補足情報(言語/FW/ツール等のバージョンなど)
Xcode8 swift3

 
###追記 2017.12.6
階層の解釈として、

MPMediaQuery

.artists() ← アーティストで分けますというメソッド

.collections ← 各アーティストがどのような曲(items)を持っているのかという情報

.items ← 各曲の詳細を内包した情報

.artistなど ←各曲の情報

これであっているでしょうか?

つまり、上記コードでは
アーティストの数だけfor文が回されているだけでなく、曲の数だけfor文が回されるのがアーティストの数だけ繰り返されていた

ということですかね?

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

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

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

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

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

fuzzball

2017/12/04 00:54

let artistItems: [MPMediaItemCollection] = artistQuery.collections! の artistItems.count はアーティスト数になってますか?
mitci

2017/12/04 12:41 編集

print(artistItems.count)を入れて実行したところ、アーティスト数になっていました・・・ ということは、それ以降のコードに不備があるということでしょうか? あ、ちなみに、 for songs in artistItems { array.append(songs) } となっていたために、 songsをartistsに直しました。もちろん、結果は変わらないですが・・・
fuzzball

2017/12/05 00:34 編集

こちらで試せないので想像で書きますが、artist.items でそのアーティストの曲が全て取り出されているのではないでしょうか?内側のartistItems(紛らわしいので名前変えた方がいいですよ)のcountを調べてみて下さい。そうであれば、結局すべての曲(MPMediaItem)からアーティストを抜き出していることになります。そうではなくて、1つのMPMediaItemCollectionから1つのアーティストを抜き出さないといけません。MPMediaItemCollectionについてもう少し調べてみて下さい。
mitci

2017/12/05 12:26

すいません。本を見ながらやったのでcollectionとitemがごちゃごちゃになっていました・・・。内側のartistItemsですが、総曲数でもアーティスト数でもない中途半端な数値になっていました。MPMediaItemCollectionとMPMediaItemの違いというか、上下関係もよくわかっておらず(参考にした本はこのコードをとりあえず書いておけ、という説明でした・・・)とりあえず、5時間くらい考えて調べてもわからなかったのですが、ちょっと追記をしてみたので読んでいただけるとありがたいです。
mitci

2017/12/06 12:26

なんとか解決にいたりました。ちょっと強引な気もしますが、どうでしょうか・・・
guest

回答1

0

自己解決

swift

1func getArtistInfo() -> Array<MPMediaItem> { 2 var array = Array<MPMediaItem>() 3 let artistQuery: MPMediaQuery = MPMediaQuery.artists() 4 let artistCollections: [MPMediaItemCollection] = artistQuery.collections! 5 for artist in artistCollections { 6 let artistItems: [MPMediaItem] = artist.items 7 for artists in artistItems { 8 array.append(artists) 9 } 10 } 11 return array 12 }

では、artistCollectionsの数だけ、artistCollections内の曲の数だけappendを繰り返しているため、単純に中のforループを取り除き、かつ、一つ目の要素(そのartistCollectionsの持つ、一曲目に当たるitem)のみを取り出してappendし、tableに入れるときに、.artistを指定して、
各アーティストの一曲目につけられている``.artist`を取り出すことで、すべてのアーティストを羅列しています。

swift

1func getArtistInfo() -> Array<MPMediaItem> { 2 var array = Array<MPMediaItem>() 3 let artistQuery: MPMediaQuery = MPMediaQuery.artists() 4 let artistCollections: [MPMediaItemCollection] = artistQuery.collections! 5 for artist in artistCollections { 6 let artistItems: [MPMediaItem] = artist.items 7 array.append(artistItems[0]) 8 } 9 return array 10 }

と、思っていたのですが、
fuzzballさんのコメントにより、

swift

1func getArtistInfo() -> Array<String> { 2 var array = Array<String>() 3 let artistQuery: MPMediaQuery = MPMediaQuery.artists() 4 let artistCollections: [MPMediaItemCollection] = artistQuery.collections! 5 for artist in artistCollections { 6 array.append((artist.representativeItem?.artist)!) 7 } 8 return array 9 }

とrepresetiveItemを使うことで解決しました。

投稿2017/12/06 12:24

編集2017/12/07 11:51
mitci

総合スコア37

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

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

fuzzball

2017/12/06 13:44

あるのか無いのかは分かりませんが、MPMediaItemCollectionからアーティスト名を取り出す方法が見つかるまでは、これで良いのではないかと思います。 ちなみに一曲目を取り出すところは、直接 array.append(artist.items.first) でいけると思います。
mitci

2017/12/06 14:37

せっかくMediaQuely.artists()が用意されているのだし、ありそうな気がしますよね… もちろん、これなら応用も効くのでしょうが…… とにかく、ありがとうございました! 職場でコメントを読み返していたら ああ、そうか!といきなり理解が進みました…笑
fuzzball

2017/12/07 04:16 編集

ドキュメントを眺めていて見つけました。 .representativeItem でコレクション内の共通な値を取得できるようです。 array.append(artist.representativeItem.artist) でいけると思います。 (適当にアンラップして下さい)
mitci

2017/12/07 11:52 編集

どこかで、見た記憶はあるのですが、完全にスルーしてしまっていました・・・ array.append((artist.representativeItem?.artist)!) ちなみに、回答は新たに書いていただければそちらを回答とさせていただきますが、どうしましょう? でいけました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問