Created
December 21, 2020 05:59
-
-
Save hishnash/c4ce28f749a87dd9502a30af34b1b266 to your computer and use it in GitHub Desktop.
Access to the underlying UIWindow & NSWindow in swiftUI gives access to window methods and attributes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ExampleWindowReaderApp.swift | |
// Shared | |
// | |
// Created by Matthaus Woolard on 21/12/2020. | |
// | |
import SwiftUI | |
@main | |
struct ExampleWindowReaderApp: App { | |
var body: some Scene { | |
WindowGroup { | |
ContentView().modifier(WindowObservationModifier()) | |
} | |
} | |
} | |
#if canImport(UIKit) | |
typealias Window = UIWindow | |
#elseif canImport(AppKit) | |
typealias Window = NSWindow | |
#else | |
#error("Unsupported platform") | |
#endif | |
class WindowObserver: ObservableObject { | |
@Published | |
public private(set) var isKeyWindow: Bool = false | |
private var becomeKeyobserver: NSObjectProtocol? | |
private var resignKeyobserver: NSObjectProtocol? | |
weak var window: Window? { | |
didSet { | |
self.isKeyWindow = window?.isKeyWindow ?? false | |
guard let window = window else { | |
self.becomeKeyobserver = nil | |
self.resignKeyobserver = nil | |
return | |
} | |
self.becomeKeyobserver = NotificationCenter.default.addObserver( | |
forName: Window.didBecomeKeyNotification, | |
object: window, | |
queue: .main | |
) { (n) in | |
self.isKeyWindow = true | |
} | |
self.resignKeyobserver = NotificationCenter.default.addObserver( | |
forName: Window.didResignKeyNotification, | |
object: window, | |
queue: .main | |
) { (n) in | |
self.isKeyWindow = false | |
} | |
} | |
} | |
} | |
extension EnvironmentValues { | |
struct IsKeyWindowKey: EnvironmentKey { | |
static var defaultValue: Bool = false | |
typealias Value = Bool | |
} | |
fileprivate(set) var isKeyWindow: Bool { | |
get { | |
self[IsKeyWindowKey.self] | |
} | |
set { | |
self[IsKeyWindowKey.self] = newValue | |
} | |
} | |
} | |
struct WindowObservationModifier: ViewModifier { | |
@StateObject | |
var windowObserver: WindowObserver = WindowObserver() | |
func body(content: Content) -> some View { | |
content.background( | |
HostingWindowFinder { [weak windowObserver] window in | |
windowObserver?.window = window | |
} | |
).environment(\.isKeyWindow, windowObserver.isKeyWindow) | |
} | |
} | |
#if canImport(UIKit) | |
struct HostingWindowFinder: UIViewRepresentable { | |
var callback: (Window?) -> () | |
func makeUIView(context: Context) -> UIView { | |
let view = UIView() | |
view.translatesAutoresizingMaskIntoConstraints = false | |
DispatchQueue.main.async { [weak view] in | |
self.callback(view?.window) | |
} | |
return view | |
} | |
func updateUIView(_ uiView: UIView, context: Context) { | |
} | |
} | |
#elseif canImport(AppKit) | |
struct HostingWindowFinder: NSViewRepresentable { | |
var callback: (Window?) -> () | |
func makeNSView(context: Self.Context) -> NSView { | |
let view = NSView() | |
view.translatesAutoresizingMaskIntoConstraints = false | |
DispatchQueue.main.async { [weak view] in | |
self.callback(view?.window) | |
} | |
return view | |
} | |
func updateNSView(_ nsView: NSView, context: Context) {} | |
} | |
#else | |
#error("Unsupported platform") | |
#endif |
@xwischi does this package build and work? https://github.com/LostMoa/KeyWindow
It's probably the fileprivate(set) var isKeyWindow: Bool
... part
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Same to me on Xcode 12.4