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

Stage Manager/Split View下iOS多窗口尺寸监听及适配方案咨询

替代解决方案

以下是几种无需通过BaseVC发送通知的实现方式:

1. 监听UIWindowScene的几何变化

主窗口所属的UIWindowScene的effectiveGeometry属性会在Stage Manager/分屏模式下实时更新。你可以在主窗口的SceneDelegate中通过KVO监听该属性变化,同步调整自定义窗口的尺寸:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    private var observation: NSKeyValueObservation?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        // 监听effectiveGeometry变化
        observation = windowScene.observe(\.effectiveGeometry, options: [.new]) { [weak self] scene, change in
            guard let newGeometry = change.newValue else { return }
            self?.adjustCustomWindowSize(with: newGeometry.size)
        }
    }

    private func adjustCustomWindowSize(with mainSize: CGSize) {
        // 根据主窗口尺寸计算自定义窗口目标尺寸
        let targetSize = CGSize(width: mainSize.width * 0.3, height: mainSize.height * 0.4)
        if let customWindow = CustomWindowManager.shared.window {
            customWindow.frame = CGRect(origin: customWindow.frame.origin, size: targetSize)
        }
    }
}

2. 直接监听主窗口的frame变化

通过KVO监听主窗口的frame属性,一旦尺寸变化就触发自定义窗口的调整逻辑:

class CustomWindowManager {
    static let shared = CustomWindowManager()
    var window: UIWindow?
    private var windowFrameObservation: NSKeyValueObservation?

    func setup(with mainWindow: UIWindow) {
        // 初始化配置自定义窗口...
        // 监听主窗口frame变化
        windowFrameObservation = mainWindow.observe(\.frame, options: [.new]) { [weak self] window, change in
            guard let newFrame = change.newValue else { return }
            self?.updateCustomWindowSize(mainWindowSize: newFrame.size)
        }
    }

    private func updateCustomWindowSize(mainWindowSize: CGSize) {
        window?.frame.size = CGSize(width: mainWindowSize.width * 0.25, height: mainWindowSize.height * 0.35)
    }
}

3. 使用AutoLayout绑定主窗口尺寸

如果自定义窗口尺寸是主窗口的固定比例,直接通过AutoLayout约束绑定两者的尺寸关系,无需手动监听事件:

func setupCustomWindow(with mainWindow: UIWindow) {
    guard let windowScene = mainWindow.windowScene else { return }
    let customWindow = UIWindow(windowScene: windowScene)
    customWindow.backgroundColor = .clear
    customWindow.isHidden = false

    let vc = CustomPIPViewController()
    customWindow.rootViewController = vc

    // 关闭自动布局转换,使用约束
    customWindow.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        customWindow.widthAnchor.constraint(equalTo: mainWindow.widthAnchor, multiplier: 0.3),
        customWindow.heightAnchor.constraint(equalTo: mainWindow.heightAnchor, multiplier: 0.4),
        // 绑定位置到主窗口右下角
        customWindow.trailingAnchor.constraint(equalTo: mainWindow.trailingAnchor, constant: -16),
        customWindow.bottomAnchor.constraint(equalTo: mainWindow.bottomAnchor, constant: -16)
    ])

    CustomWindowManager.shared.window = customWindow
}

主窗口尺寸变化时,自定义窗口会自动通过约束同步更新尺寸。

4. 监听系统通知(补充场景)

监听UIApplication.didChangeStatusBarOrientationNotification,该通知在Stage Manager模式下主窗口尺寸变化时也会触发:

class CustomPIPViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(mainWindowSizeChanged), name: UIApplication.didChangeStatusBarOrientationNotification, object: nil)
    }

    @objc private func mainWindowSizeChanged() {
        guard let mainWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return }
        view.window?.frame.size = CGSize(width: mainWindow.frame.width * 0.3, height: mainWindow.frame.height * 0.4)
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:55:22