NSMutableArray 的索引不是以 0 开头

Index of NSMutableArray not start with 0

我正在尝试将值(文档目录中的 MP3 文件)添加到 NSMutableArray。我正在创建一个音乐播放器,所以当一首歌曲播放完毕后,我的方法应该通过 AVAudioPlayer Delegate 播放下一首歌曲。我写了一个 if 语句并检查当前曲目是否大于 array.count 它应该播放索引为 0.

的第一首歌曲

问题是应用程序因以下错误而崩溃:fatal error: Array index out of range

然后我打印我的数组,这里发生了一些奇怪的事情:

print("all files are :\(player.MP3DirectoryFiles.count)")
print("all files  :\(player.MP3DirectoryFiles.description)") 

all files are :2

all files :(" Cake By The Ocean.mp3","LoveSong.mp3" )

看来数数还行!有 2 个文件,但问题是数组的索引以 0 开头,所以在这种情况下 player.MP3DirectoryFiles.count 应该是:1,这意味着:0,1。 [在 TABLE 视图中]

我不得不说在 table 查看 select 单元格和播放歌曲时一切正常,但在音乐结束后就会发生这种情况。 我需要一些帮助来解决这个问题,如果有帮助,这里有更多代码:

已编辑 2:

func playMusic(at:Int)  {

        let musicFile = MP3DirectoryFiles[at] as! NSString

        let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let musicURL = documentsDirectory.appendingPathComponent(musicFile.lastPathComponent)

        getDataFromTrack(file: musicURL)

        do {

            player = try AVAudioPlayer(contentsOf: musicURL)
            player.prepareToPlay()
            player.delegate = self
            appDefaults.setTrack(duration: Float(player.duration))


        } catch let error as NSError {

            print(error.description)
        }


    }



   func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {

        NotificationCenter.default.post(name: NSNotification.Name("musicIsFinished"), object: nil)
    }

另一个ViewController :

  func musicIsFinished(notification:Notification)  {

        _trackRow = appDefaults.loadTrackNumber()


        if _trackRow > player.MP3DirectoryFiles.count {

            _trackRow = 0


        } else {

            _trackRow! += 1

        }

                player.playMusic(at: _trackRow!)
                prepareToPlay()


    }

好的,你的数组中有两首歌。

当您开始播放第一首歌曲时,您说...在位置 0 播放歌曲(因为 NSMutableArrays 是从零开始的...正如您所知:))

一旦歌曲结束,您的 musicIsFinished 方法就会被调用。

在这里您可以查看接下来要播放的内容。

目前 _trackRow 是 0,因为那是你刚刚播放的歌曲,player.MP3DirectoryFiles.count 是 2。

您的代码如下所示:

if _trackRow > player.MP3DirectoryFiles.count {
    _trackRow = 0
} else {
    _trackRow! += 1
}

所以你最终进入 else_trackRow 递增,现在为 1。

接下来你问 playSong(at: 1) 就可以了(我希望 :))

好的...下一首歌曲已完成,我们回到 musicIsFinished_trackRow 是 1 而 player.MP3DirectoryFiles.count 仍然是 2

那么,你再检查一下:

if _trackRow > player.MP3DirectoryFiles.count

不是这样 _trackRow 递增到 2 然后你要求你的数组在索引 2

处给你歌曲

但是……索引二没有歌曲对吧?您的数组是从零开始的,因此您在索引 0 和索引 1 处有一首歌曲,但在索引 2 处没有……所以……您的应用程序变得混乱和崩溃。

你需要把你的if _trackRow > player.MP3DirectoryFiles.count转过来问:

if _trackRow < player.MP3DirectoryFiles.count - 1

意思是:

第一次你进入musicIsFinished的时候你最终进入了else部分,因为

  • _trackRow 是 0
  • player.MP3DirectoryFiles.count - 1 是 1

且0小于1

以来, 时间在 if 部分结束
  • _trackRow 是 1
  • player.MP3DirectoryFiles.count - 1 是 1

且1不小于1

说来话长,但请尝试将您的 musicIsFinished 更改为:

func musicIsFinished(notification:Notification)  {
    _trackRow = appDefaults.loadTrackNumber()

    if _trackRow < player.MP3DirectoryFiles.count - 1 {
        _trackRow += 1
    } else {
        _trackRow = 0
    }
    player.playMusic(at: _trackRow!)
    prepareToPlay()
}

希望对你有所帮助。