使用流时 AVPlayer 实例始终为 nil

AVPlayer instance always nil when using stream

我正在尝试在 swift 上实施 EventChannel 以实现 flutter 方面。所以这就是我正在做的,

我是如何注册活动频道的,

public class SwiftMusicPlayer: NSObject, FlutterPlugin {
    
    final var audioPlayer = AudioPlayer()
    
    struct Constants {
        static let methodChannelName = "MethodChannel"
        static let durationEventChannel = "durationEventChannel"
           ...
    }
    
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: Constants.methodChannelName, binaryMessenger: registrar.messenger())
        let instance = SwiftMusicPlayer()
        registrar.addMethodCallDelegate(instance, channel: channel)
        let durationChannel = FlutterEventChannel(name: Constants.durationEventChannel, binaryMessenger: registrar.messenger())
        durationChannel.setStreamHandler(AudioPlayer())
    }

// The method calls
 public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {

   let args = call.arguments as? Dictionary<String, Any>
        switch call.method {

       case Constants.preparePlayer:
            audioPlayer.preparePlayer(path: args?[Constants.path] as? String, volume: args?[Constants.volume] as? Double,result: result)
            break
        case Constants.startPlayer:
            audioPlayer.startPlayer(result: result)
            break
        case Constants.pausePlayer:
            audioPlayer.pausePlayer(result)
            break
        case Constants.stopPlayer:
            audioPlayer.stopPlayer(result)
            break
}
  }
}

AudioPlayerclass

class AudioPlayer : NSObject,FlutterStreamHandler{
    var player: AVPlayer?
    private var sink: FlutterEventSink?

// I'm initialising it using method call before doing anything
func preparePlayer(path: String?, volume: Double?,result:  @escaping FlutterResult){
        if(!(path ?? "").isEmpty){
            let url = URL.init(fileURLWithPath: path!)
            player = AVPlayer(url: url)
                player?.volume = Float(volume ?? 1.0)
                result(true)
        } else {
            result(FlutterError(code: "", message: "Path to file can't be empty or null", details: nil))
        }
    } 

func startPlayer(result:  @escaping FlutterResult){
                do{
                    if(player?.status == .readyToPlay){
                        player?.play()
                       
                        result(true)
                    }
                } catch {
                    result(FlutterError(code: "", message: "Failed to start player", details: nil))
                }
    }

func pausePlayer(_ result:  @escaping FlutterResult){
        print(player?.currentItem?.duration.seconds)
        player?.pause()
        result(true)
    }

//Here it is being nil
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
 print(self?.player?.currentItem?.asset.duration)//<---prints always nil
        sink = events
       let interval = CMTimeMakeWithSeconds(0.5, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
//never goes inside because player is nil
        player?.addPeriodicTimeObserver(forInterval: interval, queue: nil, using: {[weak self] time in
            print(time)
           
            self?.sink!(0)
        })
        return nil
    }

    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        sink = nil
        timer.invalidate()
        return nil
    }
}

在这里,当我调用启动播放器时,它会播放音频文件。暂停和停止也有效。 现在,当我在 pausePlayer() 中调用 self?.player?.currentItem?.asset.duration 时,它确实给了我持续时间,但是当我尝试在 onListen() 函数中打印它时,它总是 returns nil。

当我尝试打印 AVPlayer 的实例时,这里是 player,它也打印为 nil。

那么这里哪里做错了?

当我将 AudioPlayer() 实例传递给 setStreamHandler 时,它正在为流创建 AudioPlayer 的新实例,所以我总是 nil 所以我创建了一个单例,这样它只会创建一个副本。

class AudioPlayer : NSObject, FlutterStreamHandler {
    static let sharedInstance = AudioPlayer()
}

现在在处理程序中,

public static func register(with registrar: FlutterPluginRegistrar) {
let durationChannel = FlutterEventChannel(name: Constants.durationEventChannel, binaryMessenger: registrar.messenger())
        durationChannel.setStreamHandler(AudioPlayer.sharedInstance)
}