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

如何监听AVPlayerLayer的videoRect变化?KVO实现求助

解决AVPlayerLayer的videoRect KVO监听问题

我来帮你搞定这个KVO监听的麻烦!你当前的代码问题出在找错了监听对象——你直接试图给videoRect这个CGRect值添加观察者,但KVO的规则是要监听AVPlayerLayer对象本身的videoRect属性,而不是属性的具体值。

正确的实现步骤:

  1. 添加观察者到AVPlayerLayer对象
    把你的监听代码改成这样,针对playerLayer对象,监听videoRect这个属性的变化:

    playerLayer = AVPlayerLayer(player: player!)
    // 正确的KVO添加方式:监听playerLayer的videoRect属性
    playerLayer?.addObserver(self, forKeyPath: "videoRect", options: [.old, .new], context: nil)
    
  2. 实现KVO回调方法处理变化
    你需要在当前类中重写observeValue(forKeyPath:of:change:context:)方法,用来接收videoRect的变化通知,然后在这里处理你的图片对齐逻辑:

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        // 先判断是不是我们关心的videoRect属性变化
        guard keyPath == "videoRect", let playerLayer = object as? AVPlayerLayer else {
            // 不是的话交给父类处理
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            return
        }
        
        // 获取变化后的videoRect,执行你的图片对齐操作
        let updatedVideoRect = playerLayer.videoRect
        // 这里调用你的对齐逻辑方法
        alignImageToVideoRect(updatedVideoRect)
    }
    
  3. 记得移除观察者(避免内存泄漏)
    在当前类的销毁方法中移除观察者,防止内存泄漏:

    deinit {
        playerLayer?.removeObserver(self, forKeyPath: "videoRect")
    }
    

为什么之前的代码不行?

videoRect是AVPlayerLayer的一个属性,它的类型是CGRect,这是一个结构体,不属于NSObject子类,所以不能直接给它添加KVO观察者。KVO只能作用于继承自NSObject的对象,监听的是对象的属性名称(字符串形式)。

这样修改后,你就能监听到videoRect的变化,实时调整图片的位置,实现和视频画面的对齐了。

内容的提问来源于stack exchange,提问作者Chewie The Chorkie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:32:04