是否可以使用 AnyPublisher 包装 AVPlayer 播放和暂停
Is it possible to wrap AVPlayer Play and Pause with AnyPublisher
我正在寻找包装 AVPlayer 的播放和暂停方法,以便我可以使用 ReCombine 效果从 SwiftUI 调度操作,最终播放和暂停一些音频。
public extension AVPlayer {
func timeControlPub() -> AnyPublisher<TimeControlStatus, Never> {
publisher(for: \.timeControlStatus).eraseToAnyPublisher()
}
func playPub() -> AnyPublisher<() -> Void, Never> {
publisher(for: \.play).eraseToAnyPublisher()
}
}
上面的代码片段显示了回放的总体思路 API 和以下错误:
关键路径不能引用实例方法'play()'
我也试过
protocol PlaybackAPIManager {
func playStream() -> AnyPublisher<()-> Void, Never>
}
extension AVPlayer: PlaybackAPIManager {
func playStream() -> AnyPublisher<()-> Void, Never>{
return AVPlayer.play
}
}
但是收到错误:
无法将类型为“(AVPlayer) -> () -> Void”的 return 表达式转换为 return 类型 'AnyPublisher<() -> Void, Never>'
static let togglePlayPause = Effect(dispatch: false) { (actions: AnyPublisher<Action, Never>) in
actions.ofTypes(TogglePlay.self)
.flatMap(playStremAPI)
.print("Stream Played")
.eraseToAnyPublisher()
}
我无法使用 AnyPublisher 包装 AVPlayer 方法来安抚 ReCombine。
我不熟悉 ReCombine,所以我不清楚为什么您需要一个调用 play
方法的发布者。但这里有一种创建发布者的方法,它在您每次订阅时调用 play
方法,然后立即以 .finished
.
结束订阅
import Combine
import AVFoundation
extension AVPlayer {
func playPublisher() -> AnyPublisher<Void, Never> {
return Deferred {
(self.play(), Empty()).1
}
.eraseToAnyPublisher()
}
}
我使用了 Deferred
,所以在您订阅之前它不会调用 play
,并在每次订阅时调用 play
。
我使用了元组 (self.play(), Empty()).1
,因此闭包是单个表达式,这让 Swift 可以推导出 Deferred
.
的泛型参数
我们可以将实现概括为采用这样的闭包:
extension AnyPublisher where Output == Void, Failure == Never {
static func call(_ body: @escaping () -> Void) -> Self {
return Deferred {
(body(), Empty()).1
}
.eraseToAnyPublisher()
}
}
然后像这样使用它:
let pub = AnyPublisher.call { player.play() }
我正在寻找包装 AVPlayer 的播放和暂停方法,以便我可以使用 ReCombine 效果从 SwiftUI 调度操作,最终播放和暂停一些音频。
public extension AVPlayer {
func timeControlPub() -> AnyPublisher<TimeControlStatus, Never> {
publisher(for: \.timeControlStatus).eraseToAnyPublisher()
}
func playPub() -> AnyPublisher<() -> Void, Never> {
publisher(for: \.play).eraseToAnyPublisher()
}
}
上面的代码片段显示了回放的总体思路 API 和以下错误:
关键路径不能引用实例方法'play()'
我也试过
protocol PlaybackAPIManager {
func playStream() -> AnyPublisher<()-> Void, Never>
}
extension AVPlayer: PlaybackAPIManager {
func playStream() -> AnyPublisher<()-> Void, Never>{
return AVPlayer.play
}
}
但是收到错误:
无法将类型为“(AVPlayer) -> () -> Void”的 return 表达式转换为 return 类型 'AnyPublisher<() -> Void, Never>'
static let togglePlayPause = Effect(dispatch: false) { (actions: AnyPublisher<Action, Never>) in
actions.ofTypes(TogglePlay.self)
.flatMap(playStremAPI)
.print("Stream Played")
.eraseToAnyPublisher()
}
我无法使用 AnyPublisher 包装 AVPlayer 方法来安抚 ReCombine。
我不熟悉 ReCombine,所以我不清楚为什么您需要一个调用 play
方法的发布者。但这里有一种创建发布者的方法,它在您每次订阅时调用 play
方法,然后立即以 .finished
.
import Combine
import AVFoundation
extension AVPlayer {
func playPublisher() -> AnyPublisher<Void, Never> {
return Deferred {
(self.play(), Empty()).1
}
.eraseToAnyPublisher()
}
}
我使用了 Deferred
,所以在您订阅之前它不会调用 play
,并在每次订阅时调用 play
。
我使用了元组 (self.play(), Empty()).1
,因此闭包是单个表达式,这让 Swift 可以推导出 Deferred
.
我们可以将实现概括为采用这样的闭包:
extension AnyPublisher where Output == Void, Failure == Never {
static func call(_ body: @escaping () -> Void) -> Self {
return Deferred {
(body(), Empty()).1
}
.eraseToAnyPublisher()
}
}
然后像这样使用它:
let pub = AnyPublisher.call { player.play() }