应用程序只显示一个单元格(一首歌曲)而不是所有单元格

App only shows one cell (one song) as opposed to all of them

我目前正在编写一个应用程序,但无法弄清楚如何将这个特定的 Objective-C 行转换为 swift。任何帮助都感激不尽。我已经能够很好地翻译其他行,但是这一行会引发一些异常错误。这是原始的 Objective-C 行:

MPMediaItem *rowItem = [songs objectAtIndex: indexPath.row];

我是菜鸟,尝试过很多变体,包括:

var rowItem = songs.objectAtIndex(indexPath.row) as MPMediaItem

var rowItem: MPMediaItem = songs.objectAtIndex(indexPath.row) as MPMediaItem

但我已经在这太久了,我看不出它应该是什么。非常感谢!

编辑:

歌曲定义为:

let songsQuery = MPMediaQuery.songsQuery()
let songs = [songsQuery.items] as NSArray

我刚收到一个 exe_breakpoint 错误。如果我通过使用 ... as [MPMediaItem] 将 MPMediaItem 封装在一个数组中,我可以解决这个问题,但是我无法获得 属性 值,例如MPMediaItemPropertyTitle 和 MPMediaItemPropertyArtist。

更新: 通过使用 for 循环获取 MPMediaItemPropertyTitle 和 MPMediaPropertyArtist 设法让它工作。 'songs' 变量的定义如我上面所写。 @Antonio,删除括号没有用。这是我当前的代码:

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell

    // Configure the cell...

    let songsQuery = MPMediaQuery.songsQuery()
    let allSongsArray = [songsQuery.items] as NSArray

    var singleItem: AnyObject = allSongsArray[indexPath.row]

    var rowItem = singleItem as [MPMediaItem]

    if rowItem.count > 0 {

        cell.textLabel?.text = rowItem[0].valueForProperty(MPMediaItemPropertyTitle) as NSString
        cell.detailTextLabel?.text = rowItem[0].valueForProperty(MPMediaItemPropertyArtist) as NSString
    }

    return cell
}

我现在遇到的问题是,当我测试该应用程序时,它只显示我音乐库中的第一首歌曲,并没有像预期的那样列出每首歌曲。感谢您提供的任何帮助!

更新 2:

使用以下代码得到它:

class SongsViewController: UITableViewController {

var allSongs : [MPMediaItem] = []

override func viewDidLoad() {
    super.viewDidLoad()

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    allSongs += MPMediaQuery.songsQuery().items as [MPMediaItem]
    println(allSongs.count)

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem()
}

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete method implementation.
    // Return the number of rows in the section.

    return allSongs.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell

    // Configure the cell...

    var rowItem = allSongs[indexPath.row]

    cell.textLabel?.text = rowItem.valueForProperty(MPMediaItemPropertyTitle) as NSString
    cell.detailTextLabel?.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as NSString

    return cell
}
let allSongsArray = [songsQuery.items] as NSArray

这里你拿一个 Array<AnyObject>! 并将它包裹在另一个 Array 中,然后将其转换为 NSArray... 相当混乱。

试试这个:

let songsQuery = MPMediaQuery.songsQuery()
let allSongs = songsQuery.items as [MPMediaItem]
let song = allSongs[indexPath.row]

cell.textLabel?.text = song.valueForProperty(MPMediaItemPropertyTitle) as String
cell.detailTextLabel?.text = song.valueForProperty(MPMediaItemPropertyArtist) as String

此外,您确实应该缓存 allSongs 而不是每次需要填充单元格时都查询它。为此,只需创建添加一个 var allSongs: [MPMediaItem] = [] 到您的控制器。然后在例如 viewDidLoad 中使用 MPMediaQuery 来填充该数组。然后,您可以在任何 table 视图委托和数据源方法中使用该数组。

我认为你犯的错误是在 cellForRowAtIndexPath 中加载整个数据源,而这应该在另一个地方完成(viewDidLoad 是一个很好的选择),最重要的是一次而不是每一行。

我重新编写了您的代码,并提出了以下代码:

class TestViewController : UITableViewController {
    var allSongsArray: [MPMediaItem]!

    override func viewDidLoad() {
        super.viewDidLoad()

        let songsQuery = MPMediaQuery.songsQuery()
        self.allSongsArray = songsQuery.items as [MPMediaItem]

        // Other initializations
        ...
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.allSongsArray.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell

        var rowItem = self.allSongsArray[indexPath.row]

        cell.textLabel?.text = rowItem[0].valueForProperty(MPMediaItemPropertyTitle) as NSString
        cell.detailTextLabel?.text = rowItem[0].valueForProperty(MPMediaItemPropertyArtist) as NSString

        return cell
    }
}
var allSongs : [MPMediaItem] = []

override func viewDidLoad() {
super.viewDidLoad()

// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false

allSongs += MPMediaQuery.songsQuery().items as [MPMediaItem]
println(allSongs.count)

// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete method implementation.
    // Return the number of rows in the section.

    return allSongs.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell

    // Configure the cell...

var rowItem = allSongs[indexPath.row]

cell.textLabel?.text = rowItem.valueForProperty(MPMediaItemPropertyTitle) as NSString
cell.detailTextLabel?.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as NSString

return cell

}