【问题标题】:Is it possible to wrap AVPlayer Play and Pause with AnyPublisher是否可以用 AnyPublisher 包装 AVPlayer 播放和暂停
【发布时间】:2021-03-08 22:47:39
【问题描述】:

我正在寻找包装 AVPlayer 的播放和暂停方法,以便我可以使用 ReCombine 效果从 SwiftUI 调度操作,最终播放和暂停一些音频。

public extension AVPlayer {
    func timeControlPub() -> AnyPublisher<TimeControlStatus, Never> {
        publisher(for: \.timeControlStatus).eraseToAnyPublisher()
        
    }
    
    func playPub() -> AnyPublisher<() -> Void, Never> {
        publisher(for: \.play).eraseToAnyPublisher()
    }
}

上面的 sn-p 显示了播放 API 的一般概念和错误:

关键路径不能引用实例方法'play()'

我也试过

protocol PlaybackAPIManager {
    func playStream() -> AnyPublisher<()-> Void, Never>
}

extension AVPlayer: PlaybackAPIManager {
    func playStream() -> AnyPublisher<()-> Void, Never>{
        return AVPlayer.play
    }
}

但收到错误:

无法将“(AVPlayer) -> () -> Void”类型的返回表达式转换为“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。

【问题讨论】:

    标签: swift avfoundation avplayer combine


    【解决方案1】:

    我不熟悉 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() }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-02
      • 2011-11-12
      • 2011-11-26
      • 1970-01-01
      相关资源
      最近更新 更多