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
相关产品推荐
相关产品推荐

