gpt4 book ai didi

ios - 擦洗时跳动的 UISlider - 将 UISlider 与 AVPlayer 一起使用

转载 作者:可可西里 更新时间:2023-11-01 01:25:36 26 4
gpt4 key购买 nike

我正在使用 AvPlayer 并尝试设置一个 slider 以允许删除音频文件。我在选定时遇到了问题。然后它会回到原始位置一秒钟,然后再回到它被拖动到的位置。

你在 Gif 上看不到我的光标,但平滑的拉长拖动是我移动旋钮,然后快速鞭打是 slider 行为不端。

enter image description here

我花了几个小时在谷歌上搜索和梳理 Stack Overflow,但无法弄清楚我在这里做错了什么,很多类似的问题已经很老了,而且在 ObjC 中。

我认为这是导致问题的代码部分,它确实处理了移动 slider 的事件:我在没有 if 语句的情况下也尝试过,但没有看到不同的结果。

@IBAction func horizontalSliderActioned(_ sender: Any) {

horizontalSlider.isContinuous = true

if self.horizontalSlider.isTouchInside {

audioPlayer?.pause()
let seconds : Int64 = Int64(horizontalSlider.value)
let preferredTimeScale : Int32 = 1
let seekTime : CMTime = CMTimeMake(seconds, preferredTimeScale)
audioPlayerItem?.seek(to: seekTime)
audioPlayer?.play()

} else {

let duration : CMTime = (self.audioPlayer?.currentItem!.asset.duration)!
let seconds : Float64 = CMTimeGetSeconds(duration)
self.horizontalSlider.value = Float(seconds)
}
}

我将在下面包括我的整个类(class)以供引用。

import UIKit
import Parse
import AVFoundation
import AVKit


class PlayerViewController: UIViewController, AVAudioPlayerDelegate {

@IBOutlet var horizontalSlider: UISlider!

var selectedAudio: String!

var audioPlayer: AVPlayer?
var audioPlayerItem: AVPlayerItem?

var timer: Timer?


func getAudio() {

let query = PFQuery(className: "Part")
query.whereKey("objectId", equalTo: selectedAudio)
query.getFirstObjectInBackground { (object, error) in

if error != nil || object == nil {
print("The getFirstObject request failed.")

} else {
print("There is an object now get the Audio. ")

let audioFileURL = (object?.object(forKey: "partAudio") as! PFFile).url
self.audioPlayerItem = AVPlayerItem(url: NSURL(string: audioFileURL!) as! URL)
self.audioPlayer = AVPlayer(playerItem: self.audioPlayerItem)
let playerLayer = AVPlayerLayer(player: self.audioPlayer)
playerLayer.frame = CGRect(x: 0, y: 0, width: 10, height: 10)
self.view.layer.addSublayer(playerLayer)

let duration : CMTime = (self.audioPlayer?.currentItem!.asset.duration)!
let seconds : Float64 = CMTimeGetSeconds(duration)
let maxTime : Float = Float(seconds)
self.horizontalSlider.maximumValue = maxTime

self.audioPlayer?.play()

self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(PlayerViewController.audioSliderUpdate), userInfo: nil, repeats: true)
}
}
}


@IBOutlet var playerButton: UIButton!


func playerButtonTapped() {

if audioPlayer?.rate == 0 {
audioPlayer?.play()
self.playerButton.setImage(UIImage(named: "play"), for: UIControlState.normal)

} else {
audioPlayer?.pause()
self.playerButton.setImage(UIImage(named: "pause"), for: UIControlState.normal)
}

}


override func viewDidLoad() {
super.viewDidLoad()

horizontalSlider.minimumValue = 0
horizontalSlider.value = 0

self.playerButton.addTarget(self, action: #selector(PlayerViewController.playerButtonTapped), for: UIControlEvents.touchUpInside)

getAudio()
}



override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

NotificationCenter.default.addObserver(self, selector: #selector(PlayerViewController.finishedPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: self.audioPlayerItem)

}



override func viewWillDisappear(_ animated: Bool) {
super.viewWillAppear(animated)
// remove the timer
self.timer?.invalidate()
// remove the observer when leaving page
NotificationCenter.default.removeObserver(audioPlayer?.currentItem! as Any)
}



func finishedPlaying() {

// need option to play next track

self.playerButton.setImage(UIImage(named: "play"), for: UIControlState.normal)

let seconds : Int64 = 0
let preferredTimeScale : Int32 = 1
let seekTime : CMTime = CMTimeMake(seconds, preferredTimeScale)

audioPlayerItem!.seek(to: seekTime)
}

@IBAction func horizontalSliderActioned(_ sender: Any) {

horizontalSlider.isContinuous = true

if self.horizontalSlider.isTouchInside {

audioPlayer?.pause()
let seconds : Int64 = Int64(horizontalSlider.value)
let preferredTimeScale : Int32 = 1
let seekTime : CMTime = CMTimeMake(seconds, preferredTimeScale)
audioPlayerItem?.seek(to: seekTime)
audioPlayer?.play()

} else {

let duration : CMTime = (self.audioPlayer?.currentItem!.asset.duration)!
let seconds : Float64 = CMTimeGetSeconds(duration)
self.horizontalSlider.value = Float(seconds)
}
}



func audioSliderUpdate() {

let currentTime : CMTime = (self.audioPlayerItem?.currentTime())!
let seconds : Float64 = CMTimeGetSeconds(currentTime)
let time : Float = Float(seconds)
self.horizontalSlider.value = time
}

}

最佳答案

swift 5、Xcode 11

我遇到了同样的问题,显然是 periodicTimeObserver 导致返回不正确的时间,导致 slider 滞后或跳跃。我通过在 slider 更改时删除周期性时间观察器并在调用查找完成处理程序时将其添加回来解决了这个问题。

@objc func sliderValueChanged(_ playbackSlider: UISlider, event: UIEvent){

let seconds : Float = Float(playbackSlider.value)
let targetTime:CMTime = CMTimeMake(value: Int64(seconds), timescale: 1)


if let touchEvent = event.allTouches?.first {
switch touchEvent.phase {
case .began:
// handle drag began
//Remove observer when dragging is in progress
self.removePeriodicTimeObserver()


break
case .moved:
// handle drag moved

break
case .ended:
// handle drag ended

//Add Observer back when seeking got completed
player.seek(to: targetTime, toleranceBefore: .zero, toleranceAfter: .zero) { [weak self] (value) in
self?.addTimeObserver()
}

break
default:
break
}
}
}

关于ios - 擦洗时跳动的 UISlider - 将 UISlider 与 AVPlayer 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41755993/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com