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 |
@xiaoxidong That is a strange error to get. What version of Xcode are you running? And have you cleaned your build folder?
Same to me on Xcode 12.4
@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
I add this code to my project and has a error? any idea why? The error below.
Undefined symbols for architecture x86_64:
"(extension in Poke):SwiftUI.EnvironmentValues.isKeyWindow.setter : Swift.Bool", referenced from:
key path setter for (extension in Poke):SwiftUI.EnvironmentValues.isKeyWindow : Swift.Bool : SwiftUI.EnvironmentValues in PokeApp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)