我试图创建一个简单的音乐播放器,将UITableView
分割成字母部分(如 Apple音乐播放器)列出设备上的所有歌曲。< / p>
有两个方面我无法弄清楚:
我的代码已经很长了所以我会在这里提供相关信息:
我得到这样的歌曲列表:
let songsQry:MPMediaQuery = MPMediaQuery.songsQuery()
这是我不确定的地方:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//How can I get the number of songs per Section to return??
// this does not work:
return songsQry.itemSections![0].count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
//How do I get the song for the Section and Row??
cell.textLabel?.text = ????
return cell
}
答案 0 :(得分:3)
我要回答我自己的问题 我在这里发布了类似的问题,所有人都回答说无法完成,需要额外的数组加上自定义排序例程。这根本不是真的。
但请注意,在我的示例代码中,我展示了如何为相册查询获得相同类型的结果。 Artist查询的代码几乎完全相同。
此代码使用从相册查询返回到:
1)构建TableView索引
2)按标题添加专辑(使用Apple的排序)到表格部分
3)选择时开始播放专辑
这是证明它的Swift代码:
// Set up a basic Albums query
let qryAlbums = MPMediaQuery.albumsQuery()
qryAlbums.groupingType = MPMediaGrouping.Album
// This chunk handles the TableView Index
//create index title
func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
let sectionIndexTitles = qryAlbums.itemSections!.map { $0.title }
return sectionIndexTitles
}
func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
return index
}
// This chunk sets up the table Sections and Headers
//tableview
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return (qryAlbums.itemSections![section].title)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return (qryAlbums.itemSections?.count)!
}
// Get the number of rows per Section - YES SECTIONS EXIST WITHIN QUERIES
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return qryAlbums.collectionSections![section].range.length
}
// Set the cell in the table
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
// i'm only posting the pertinent Album code here.
// you'll need to set the cell details yourself.
let currLoc = qryAlbums.collectionSections![indexPath.section].range.location
let rowItem = qryAlbums.collections![indexPath.row + currLoc]
//Main text is Album name
cell.textLabel!.text = rowItem.items[0].albumTitle
// Detail text is Album artist
cell.detailTextLabel!.text = rowItem.items[0].albumArtist!
// Or number of songs from the current album if you prefer
//cell.detailTextLabel!.text = String(rowItem.items.count) + " songs"
// Add the album artwork
var artWork = rowItem.representativeItem?.artwork
let tableImageSize = CGSize(width: 10, height: 10) //doesn't matter - gets resized below
let cellImg: UIImageView = UIImageView(frame: CGRectMake(0, 5, myRowHeight-10, myRowHeight-10))
cellImg.image = artWork?.imageWithSize(tableImageSize)
cell.addSubview(cellImg)
return cell
}
// When a user selects a table row, start playing the album
// This assumes the myMP has been properly declared as a MediaPlayer
// elsewhere in code !!!
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currLoc = qryAlbums.collectionSections![indexPath.section].range.location
myMP.setQueueWithItemCollection(qryAlbums.collections![indexPath.row + currLoc])
myMP.play()
}
另外,这里有一些有用的注释:
1)列出查询中的所有相册:
for album in allCollections!{
print("---------------")
print("albumTitle \(album.items[0].albumTitle)")
print("albumTitle \(album.representativeItem?.albumTitle)")
print("albumTitle \(album.representativeItem?.valueForProperty(MPMediaItemPropertyAlbumTitle))")
} // each print statement is another way to get the title
2)打印出部分查询以查看其构造方式:
print("xxxx \(qryAlbums.collectionSections)")
我希望这对你们中的一些人有所帮助 - 如果是这样的话就投票了!
答案 1 :(得分:1)
这个想法很简单:
您需要创建一个包含对象的已排序数组 GroupedSongs 类型
[String: [MPMediaItem]]
(键是字符和 数组包含与该字符对应的歌曲。该[MPMediaItem]
数组必须从title属性中排序。
设置表视图数据源
代码有评论,所以不再说话了:D
var items: [[String: [MPMediaItem]]] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
items = loadSongsDividedByTitle()
}
// MARK: - Delegation
// MARK: Table view datasource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let object: [String: [MPMediaItem]] = items[section]
let key = Array(object.keys)[0] // We always have one object there
let songs: [MPMediaItem] = object[key]!
return songs.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
// Load song from the array
let object: [String: [MPMediaItem]] = items[indexPath.section]
let key = Array(object.keys)[0] // We always have one object there
let songs: [MPMediaItem] = object[key]!
let song = songs[indexPath.row]
// Bind title of the song to the cell text label
cell.textLabel?.text = song.title
return cell
}
// MARK: - Helpers
func loadSongsDividedByTitle() -> [[String: [MPMediaItem]]] {
guard var songs = MPMediaQuery.songsQuery().items else { return [] }
// Sort songs
songs = songs.sort({$0.title < $1.title})
// Create a new dictionary to hold array of words for each letter
var object: [String: [MPMediaItem]] = [:]
// Songs holding a dictionary with music
var groupedSongs : [[String: [MPMediaItem]]] = []
// Enumerate in words
for mediaItem in songs {
guard let title: String = mediaItem.title! else { continue } // If we don't have the title skip the song
// Use the first character as a key for each array
let key = String(title.characters.first!)
if var songGroup = object[key] {
// If we have an array, then append the new word there
songGroup.append(mediaItem)
object[key] = songGroup
} else {
// Create an array for that key
object[key] = [mediaItem]
}
}
// Add every object into one big array
for (key, value) in object {
let sortedSongs = value.sort({$0.title < $1.title})
groupedSongs.append([key: sortedSongs])
}
// Sort it alphabetically from a-z
groupedSongs = groupedSongs.sort({Array($0.keys)[0] < Array($1.keys)[0]})
return groupedSongs
}