应用程序只显示一个单元格(一首歌曲)而不是所有单元格
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
}
我目前正在编写一个应用程序,但无法弄清楚如何将这个特定的 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
}