Mac Catalyst音乐播放器中歌曲时间的uilabel和UISlider未更新



我最近创建了一个简单的音乐应用程序,在我停用的iPhone上运行良好。后来我买了一台Mac mini,这样我就可以用Mac Catalyst在这个平台上运行它了。到目前为止,它适应得很好,但我受到uilabel和UISlider的阻碍,因为经过的时间和剩余的播放时间没有更新。我上周在这里研究了这个问题,但还没有解决方案。这包括在视图控制器激活时调用字符串变量,以及在主线程上更新标签。

我在viewDidLoad中调用定时器:

timer2 = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.tick), userInfo: nil, repeats: true)

tick函数提供一个时钟标签,显示当前时间:

@objc func tick() {
let date = Date()
labelTime.text = DateFormatter.localizedString(from: date, dateStyle: .none, timeStyle: .medium)

它还控制两个标签,用于运行时间和剩余时间,以及一个时间滑块:

if let curTrack = mp.nowPlayingItem {
//Call length of track in seconds
let trackDuration = curTrack.playbackDuration
//Get elapsed time by calling currentPlaybackTime
let trackElapsed = mp.currentPlaybackTime
// avoid crash
if trackElapsed.isNaN
{
return
}
// Display running time
let trackElapsedMins = Int(trackElapsed / 60)
let trackElapsedSecs = Int(trackElapsed.truncatingRemainder(dividingBy: 60))
if trackElapsedSecs < 10 {
labelElapsed.text = "(trackElapsedMins):0(trackElapsedSecs)"
} else {
labelElapsed.text = "(trackElapsedMins):(trackElapsedSecs)"
}
//Display remaining time: subtract elapsed from duration
let trackRemaining = Int(trackDuration) - Int(trackElapsed)
let trackRemainingMins = trackRemaining / 60

let trackRemainingSecs = trackRemaining % 60

if trackRemainingSecs < 10 {
labelRem.text = "(trackRemainingMins):0(trackRemainingSecs)"
} else {
labelRem.text = "(trackRemainingMins):(trackRemainingSecs)"
}
sliderTime.maximumValue = Float(trackDuration)
sliderTime.value = Float(trackElapsed)
}

标签和滑块是你的标准出口:

@IBOutlet weak var labelTime: UILabel!
@IBOutlet weak var labelElapsed: UILabel!
@IBOutlet weak var labelRem: UILabel!
@IBOutlet weak var sliderTime: UISlider!

我看到这个函数在工作,因为时钟忠实地计数秒,当我插入断点时,所有变量都包含数据,但是标签和滑块只在我的应用程序启动时显示音乐应用程序中正在进行的播放时间,仅此而已。滑块在操作时将跳转到歌曲中的不同点,但之后永远不会更新。所以我的问题是:是什么阻碍了Mac Catalyst的这些更新操作?

对于它的价值,我现在确定问题不在于催化剂,而是非常缺乏音乐应用程序API,它似乎只在初始化或暂停时调用正确的currentPlaybackTime,否则其值恢复为0。我在运行iOS 14的iPhone上安装了这款应用,它也有同样的问题。也许这个问题会在未来的版本中得到修复,但考虑到几个月来这里和其他地方对类似问题的抱怨,我不能屏息以待……更新:对于那些在类似的困境中找到这篇文章寻求解决方案的人,这里是我的变通方法……在拒绝了单独的计时器(太不准确)和AppleScript桥来返回玩家位置属性的值(在Mac Catalyst中可能不可能)的想法后,我发现每次我点击播放按钮时currentPlaybackTime都会刷新。所以我建立了这个函数

@objc func playTime() -> Double {
let trackElapsed = mp.currentPlaybackTime
if isPlaying == true {
mp.play()
}
return trackElapsed
}

isPlaying变量为真时每秒发送一个play命令,从而将更新的播放头位置值返回给我的标签和滑块。问题解决了…

谢谢!我从来没有想到当musicPlayer已经在播放时调用play会导致currentPlaybackTime更新。

我将这段代码添加到我现有的一秒计时器代码中,它工作得很好。正如你所提到的,如果在M1 Mac上运行,在音乐应用程序中暂停将被覆盖,但它在iOS上的功能与预期一样。

if ((previousPlaybackTime == musicPlayer.currentPlaybackTime) &&
            ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying))
        {
            NSLog(@">>>update time is same as one second ago and state is playing so try calling play to tickle currentPlaybackTime");
            musicPlayer.play;
        }

最新更新