Struggling with NotificationCenter/Combine in SwiftUI/AVPlayer(在SwiftUI/AVPlayer中艰难应对NotificationCenter/Combine)
本文介绍了在SwiftUI/AVPlayer中艰难应对NotificationCenter/Combine的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在尝试在项目播放结束时暂停AVPlayer。使用SwiftUI实现这一点的最佳方式是什么?我不太了解通知,在哪里声明它们,等等。有什么方法可以使用联合来实现这一点吗?样例代码将会非常棒!提前谢谢您。
更新:
在下面答案的帮助下,我成功地创建了一个类,它接受AVPlayer并在项目结束时发布通知。您可以通过以下方式订阅通知:
类:
import Combine
import AVFoundation
class PlayerFinishedObserver {
let publisher = PassthroughSubject<Void, Never>()
init(player: AVPlayer) {
let item = player.currentItem
var cancellable: AnyCancellable?
cancellable = NotificationCenter.default.publisher(for: .AVPlayerItemDidPlayToEndTime, object: item).sink { [weak self] change in
self?.publisher.send()
print("Gotcha")
cancellable?.cancel()
}
}
}
添加到您的结构:
let finishedObserver: PlayerFinishedObserver
订阅某些视图:
.onReceive(finishedObserver.publisher) {
print("Gotcha!")
}
推荐答案
我为类似问题找到了一个解决方案:
- 我创建了
AVPlayer
; 的新子类
- 将观察者添加到
currentItem
; - 覆盖函数
observeValue
,其中当玩家到达结束时间时为当前物品添加观察者;
这里有一个简化的例子:
import AVKit // for player
import Combine // for observing and adding as environmentObject
final class AudioPlayer: AVPlayer, ObservableObject {
var songDidEnd = PassthroughSubject<Void, Never>() // you can use it in some View with .onReceive function
override init() {
super.init()
registerObserves()
}
private func registerObserves() {
self.addObserver(self, forKeyPath: "currentItem", options: [.new], context: nil)
// example of using
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
// currentItem could be nil in the player. I add observer to exist item
if keyPath == "currentItem", let item = currentItem {
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying(_:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: item)
// another way, using Combine
var cancellable: AnyCancellable?
cancellable = NotificationCenter.default.publisher(for: .AVPlayerItemDidPlayToEndTime, object: item).sink { [weak self] _ in
self?.songDidEnd.send()
cancellable?.cancel()
}
}
// other observers
}
@objc private func playerDidFinishPlaying(_ notification: Notification) {
playNextSong() // my implementation, here you can just write: "self.pause()"
}
}
UPDATE:使用.onReceive
的简单示例(请注意,我编写它时没有使用playround/Xcode,所以它可能会有错误):
struct ContentView: View {
@EnvironmentObject var audioPlayer: AudioPlayer
@State private var someText: String = "song is playing"
var body: some View {
Text(someText)
.onReceive(self.audioPlayer.songDidEnd) { // maybe you need "_ in" here
self.handleSongDidEnd()
}
}
private func handleSongDidEnd() {
print("song did end")
withAnimation {
someText = "song paused"
}
}
}
关于Combine
和AVPlayer
:您可以查看我的question,在SwiftUI
中可以看到一些观察播放时间的方法和使用滑块倒带时间的功能。
我正在使用AudioPlayer
的一个实例,控制播放/暂停功能或更改currentItem
(这意味着设置另一首歌曲),如下所示:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// other staff
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let homeView = ContentView()
.environmentObject(AudioPlayer())
// other staff of SceneDelegate
}
}
这篇关于在SwiftUI/AVPlayer中艰难应对NotificationCenter/Combine的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
沃梦达教程
本文标题为:在SwiftUI/AVPlayer中艰难应对NotificationCenter/Combine
基础教程推荐
猜你喜欢
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- Android:对话框关闭而不调用关闭 2022-01-01
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01