You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter iOS PlatformView嵌入AVPlayer报override错误及黑屏问题

问题原因

编译错误触发原因

'override' can only be specified on class members 报错根源有两个:

  1. 你把viewDidLoad()方法写在了createNativeView函数内部,属于嵌套函数,不属于类的成员方法,无法使用override标记
  2. 你的VideoView类继承自NSObject、实现FlutterPlatformView协议,本身不是UIViewController或者UIView的子类,根本不存在viewDidLoad这个可重写的生命周期方法。

黑屏触发原因

你在初始化AVPlayerLayer时直接取self._view.bounds赋值,此时_view刚被创建,还没完成Flutter端传入的布局约束适配,bounds默认是.zero,导致播放器图层尺寸为0,无法正常渲染。另外你没有持有AVPlayer实例,局部变量出作用域后会被系统回收,也会导致播放失败。


修复后的可运行代码
import UIKit
import Flutter
import AVKit
import AVFoundation

public class VideoView: NSObject, FlutterPlatformView {
    // 持有播放器实例,避免被提前释放
    private var player: AVPlayer?
    private var playerLayer: AVPlayerLayer?
    private let _view: UIView
    
    init(
         frame: CGRect,
         viewIdentifier viewId: Int64,
         arguments args: Any?,
         binaryMessenger messenger: FlutterBinaryMessenger?
    ) {
        _view = UIView()
        _view.backgroundColor = .black
        super.init()
        createNativeView()
    }
    
    public func view() -> UIView {
        return _view
    }
    
    // 视图布局更新时自动调整播放器图层尺寸,解决黑屏问题
    public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "bounds", let view = object as? UIView, view == _view {
            playerLayer?.frame = view.bounds
        }
    }
    
    private func createNativeView(){
        // 替换成你的真实视频地址
        guard let url = URL(string: "替换为实际可访问的视频直链") else { return }
        let player = AVPlayer(url: url)
        let playerLayer = AVPlayerLayer(player: player)
        playerLayer.videoGravity = .resizeAspect
        // 初始化先给个初始frame,后续布局更新会自动调整
        playerLayer.frame = _view.bounds
        _view.layer.addSublayer(playerLayer)
        
        // 监听_view的bounds变化,实时更新播放器图层尺寸
        _view.addObserver(self, forKeyPath: "bounds", options: .new, context: nil)
        
        self.player = player
        self.playerLayer = playerLayer
        player.play()
    }
    
    deinit {
        // 移除监听、暂停播放,避免内存泄漏
        _view.removeObserver(self, forKeyPath: "bounds")
        player?.pause()
        playerLayer?.removeFromSuperlayer()
    }
}

额外注意点
  • 不要使用示例里的"link"占位字符串,必须传入可直接访问的视频直链,HTTP链接需要在iOS的Info.plist里配置ATS权限
  • 如果是播放本地视频,需要正确拼接本地文件路径,远程视频要确保设备网络可访问
  • 模拟器播放部分编码的视频可能存在兼容问题,建议用真机做最终验证

内容的提问来源于stack exchange,提问作者userName

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 23:51:24