如果播放列表计数 = 0,应用程序崩溃(空播放列表是否有 persistentid?)

App crashes if playlist count = 0 (Do empty playlists have a persistentid?)

如果播放列表为空(没有歌曲),我的应用程序就会崩溃。我的应用适用于所有非空播放列表。似乎没有空播放列表的 persistentid,但我认为我错了。

let qryPlaylists = MPMediaQuery.playlistsQuery()
var selectedPlaylistTitle: String!
var selectedPlaylistPersistentID: UInt64!

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    let indexPath: NSIndexPath = playlistsTableView.indexPathForSelectedRow!
    let rowItem = qryPlaylists.collections![indexPath.row]

    let playlistSize = rowItem.count
    print("playlistSize = ", playlistSize)

    selectedPlaylistTitle = rowItem.valueForProperty(MPMediaPlaylistPropertyName) as! String
    print("selectedPlaylistTitle = ", selectedPlaylistTitle)

    // Will crash on this next line if the playlistSize = 0
    selectedPlaylistPersistentID = rowItem.items[0].persistentID

    // If I use following line instead, it will crash on any playlist
    // selectedPlaylistPersistentID = rowItem.valueForProperty(MPMediaPlaylistPropertyPersistentID) as! UInt64

    // This line will never be printed
    print("selectedPlaylistPersistentID = ", selectedPlaylistPersistentID)

}

在此先感谢您的帮助!

如果 items 这样的数组是空的,它没有索引 0 并且如果你引用它会崩溃,并出现 out-of-bounds 错误。所以如果你不想崩溃,就不要那样做。你已经知道 items 是空的,因为 rowItem.count 告诉你了;正如您自己所说,playlistSize 在这种情况下为 0。

一种simple-minded的看待方式是这样的:数组中最大的合法索引比它的count


您询问的另一个问题是这条线总是崩溃:

selectedPlaylistPersistentID = rowItem.valueForProperty(MPMediaPlaylistPropertyPersistentID) as! UInt64

这里的问题是您显然在使用 Swift 2.x。 (你应该在你的问题中这么说;不过,我是从 valueForProperty 没有更改为 value(forProperty:) 的事实推断出来的,这就是 Swift 3 中的名称。)

在Swift2中,不能直接向下转换为UInt64。 (令我惊讶的是,编译器没有通过警告提醒您注意这一事实。)因此,转换失败,您崩溃了。您需要向下转换为 NSNumber,然后取该 NSNumber 的 unsignedLongLongValue.

在执行此操作时,您真的应该停止在代码中使用感叹号。当我说 "cast down" 时,我的意思是 "cast down safely"。我自己的 Swift 2 执行此类操作的代码如下所示:

if let id = (rowItem.valueForProperty(MPMediaItemPropertyAlbumPersistentID) as? NSNumber)?.unsignedLongLongValue {
    // ...
}