是否可以使用 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() }