0

在我的 AppDelegate 中,我有这个方法,它会在单击播放按钮时运行:

- (IBAction)actionPlayTrack:(id)sender {
    NSSound *currentSong = [[NSSound alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"03 Bazel" ofType:@"mp3"] byReference:YES];
    if([currentSong isPlaying] == NO){
        [currentSong play];
    } else {
        [currentSong stop];
        [currentSong release];
    }
}

但是,用于检查歌曲当前是否正在播放的 if 语句将不起作用,并且无论是否已经播放声音,都将始终播放。关于它为什么会这样做的任何想法?也许每次单击按钮时都会重置 currentSong 对象,这将是我的第一个猜测......

[currentSong isPlaying] 

将始终返回 null。

4

3 回答 3

3

我相信问题在于每次调用此方法时都会创建一个新的 NSSound 实例。所以旧的 NSSound 实例可能正在播放,但这个不是。这可能会导致内存泄漏,因为您分配了一个新实例,但从不释放旧实例。

为了克服这个问题,你可能想在你的类中添加一个 NSSound *currentSong,然后当你想检查它是否正在播放时,你可以使用这个 NSSound 对象。然后,当您切换轨道时,您可能希望停止现有的 NSSound 对象并在创建新的 NSSound 实例之前释放它。

所以你的代码应该是这样的:

- (IBAction)actionPlayTrack:(id)sender {
    if (!currentSong) {
        currentSong = [[NSSound alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"03 Bazel" ofType:@"mp3"] byReference:YES];
    }

    if ([currentSong isPlaying]){
        [currentSong stop];
        [currentSong release];
        currentSong = nil;
    } else {
        [currentSong play];
    }
}

- (void)dealloc {
    [currentSong release];
    currentSong = nil;
}

然后添加NSSound* currentSong到您的标题中。

于 2011-11-30T15:05:23.357 回答
0

NO当您询问刚刚创建的声音是否正在播放时,它将始终返回,当然不是。

您可能需要使用 AudioSession 函数来检查设备是否已经在播放其他内容:

UInt32 otherAudioIsPlaying;
UInt32 propertySize = sizeof( UInt32 );

AudioSessionGetProperty
(
    kAudioSessionProperty_OtherAudioIsPlaying,
    &propertySize,
    &otherAudioIsPlaying
);

检查音频会话编程指南

于 2011-11-30T14:59:21.360 回答
0

此技巧可能无法解决您的问题,但切勿将任何内容与“是”或“否”进行比较。你的测试应该是:

if (![currentSong isPlaying])

原因是 NO 和 YES 是单个值,而可能被视为 true 的值是无限的。

于 2011-11-30T14:43:30.217 回答