@@ -40,14 +40,22 @@ public final class FloatingDisplayTarget {
4040 left: . activeWindow
4141 )
4242 }
43+
44+ fileprivate var containsActiveWindowEdge : Bool {
45+ top == . activeWindow
46+ || right == . activeWindow
47+ || bottom == . activeWindow
48+ || left == . activeWindow
49+ }
4350 }
4451
45- public enum TargetSafeArea {
52+ public enum TargetSafeArea : Equatable {
4653 case notificationWindow
4754 case activeWindow
4855 }
4956
5057 private let notificationWindow : NotificationWindow
58+ private let safeAreaFinder : SafeAreaFinder
5159 private let notificationViewController : NotificationViewController
5260
5361 public var additionalSafeAreaInsets : UIEdgeInsets {
@@ -69,35 +77,31 @@ public final class FloatingDisplayTarget {
6977 }
7078
7179 public func makeWindowVisible( ) {
80+ _ = notificationViewController. view
7281 notificationWindow. isHidden = false
82+
83+ if notificationViewController. needsActiveWindowSafeArea {
84+ safeAreaFinder. start ( )
85+ }
7386 }
7487
7588 public func hideWindow( ) {
7689 notificationWindow. isHidden = true
90+ safeAreaFinder. stop ( )
7791 }
7892
79- public init ( edgeTargetSafeArea: EdgeTargetSafeArea ) {
80-
81- self . notificationViewController = . init( edgeTargetSafeArea: edgeTargetSafeArea)
82-
83- if #available( iOS 13 , * ) {
84-
85- let windowScene = UIApplication . shared
86- . connectedScenes
87- . lazy
88- . filter { $0. activationState == . foregroundActive }
89- . compactMap { $0 as? UIWindowScene }
90- . first
93+ @available ( iOS 13 . 0 , * )
94+ public init (
95+ edgeTargetSafeArea: EdgeTargetSafeArea ,
96+ windowScene: UIWindowScene
97+ ) {
9198
92- if let windowScene = windowScene {
93- notificationWindow = . init( windowScene: windowScene)
94- } else {
95- notificationWindow = . init( frame: . zero)
96- }
97-
98- } else {
99- notificationWindow = . init( frame: . zero)
100- }
99+ self . safeAreaFinder = . init( windowScene: windowScene)
100+ self . notificationViewController = . init(
101+ edgeTargetSafeArea: edgeTargetSafeArea,
102+ safeAreaFinder: safeAreaFinder
103+ )
104+ self . notificationWindow = . init( windowScene: windowScene)
101105
102106 notificationWindow. windowLevel = UIWindow . Level ( rawValue: 5 )
103107 notificationWindow. isHidden = true
@@ -108,11 +112,11 @@ public final class FloatingDisplayTarget {
108112 notificationViewController. endAppearanceTransition ( )
109113 }
110114
111- deinit {
112- Task { @MainActor [ notificationWindow] in
115+ deinit {
116+ Task { @MainActor [ safeAreaFinder, notificationWindow] in
117+ safeAreaFinder. stop ( )
113118 notificationWindow. isHidden = false
114119 }
115-
116120 }
117121
118122}
@@ -149,9 +153,18 @@ extension FloatingDisplayTarget {
149153 fileprivate final class NotificationViewController : UIViewController {
150154
151155 private let edgeTargetSafeArea : EdgeTargetSafeArea
156+ private let safeAreaFinder : SafeAreaFinder
152157
153- init ( edgeTargetSafeArea: EdgeTargetSafeArea ) {
158+ fileprivate var needsActiveWindowSafeArea : Bool {
159+ edgeTargetSafeArea. containsActiveWindowEdge
160+ }
161+
162+ init (
163+ edgeTargetSafeArea: EdgeTargetSafeArea ,
164+ safeAreaFinder: SafeAreaFinder
165+ ) {
154166 self . edgeTargetSafeArea = edgeTargetSafeArea
167+ self . safeAreaFinder = safeAreaFinder
155168 super. init ( nibName: nil , bundle: nil )
156169 }
157170
@@ -160,7 +173,10 @@ extension FloatingDisplayTarget {
160173 }
161174
162175 override fileprivate func loadView( ) {
163- view = View ( edgeTargetSafeArea: edgeTargetSafeArea)
176+ view = View (
177+ edgeTargetSafeArea: edgeTargetSafeArea,
178+ safeAreaFinder: safeAreaFinder
179+ )
164180 }
165181
166182 override fileprivate func viewDidLoad( ) {
@@ -172,6 +188,7 @@ extension FloatingDisplayTarget {
172188 fileprivate class View : UIView {
173189
174190 private let edgeTargetSafeArea : EdgeTargetSafeArea
191+ private let safeAreaFinder : SafeAreaFinder
175192
176193 private var _safeAreaLayoutGuide : UILayoutGuide = . init( )
177194 private var activeWindowSafeAreaLayoutGuideConstraintLeft : NSLayoutConstraint ?
@@ -181,15 +198,19 @@ extension FloatingDisplayTarget {
181198
182199 private var hasSafeAreaFinderActivated : Bool = false
183200
184- init ( edgeTargetSafeArea: EdgeTargetSafeArea ) {
201+ init (
202+ edgeTargetSafeArea: EdgeTargetSafeArea ,
203+ safeAreaFinder: SafeAreaFinder
204+ ) {
185205
186206 self . edgeTargetSafeArea = edgeTargetSafeArea
207+ self . safeAreaFinder = safeAreaFinder
187208
188209 super. init ( frame: . zero)
189210
190211 addLayoutGuide ( _safeAreaLayoutGuide)
191212
192- var containsActievWindowSafeAreaEdge : Bool = false
213+ var containsActiveWindowSafeAreaEdge : Bool = false
193214
194215 switch edgeTargetSafeArea. top {
195216 case . notificationWindow:
@@ -198,7 +219,7 @@ extension FloatingDisplayTarget {
198219 case . activeWindow:
199220 activeWindowSafeAreaLayoutGuideConstraintTop = topAnchor. constraint (
200221 equalTo: _safeAreaLayoutGuide. topAnchor)
201- containsActievWindowSafeAreaEdge = true
222+ containsActiveWindowSafeAreaEdge = true
202223 }
203224
204225 switch edgeTargetSafeArea. right {
@@ -209,7 +230,7 @@ extension FloatingDisplayTarget {
209230 case . activeWindow:
210231 activeWindowSafeAreaLayoutGuideConstraintRight = rightAnchor. constraint (
211232 equalTo: _safeAreaLayoutGuide. rightAnchor)
212- containsActievWindowSafeAreaEdge = true
233+ containsActiveWindowSafeAreaEdge = true
213234 }
214235
215236 switch edgeTargetSafeArea. bottom {
@@ -220,7 +241,7 @@ extension FloatingDisplayTarget {
220241 case . activeWindow:
221242 activeWindowSafeAreaLayoutGuideConstraintBottom = bottomAnchor. constraint (
222243 equalTo: _safeAreaLayoutGuide. bottomAnchor)
223- containsActievWindowSafeAreaEdge = true
244+ containsActiveWindowSafeAreaEdge = true
224245 }
225246
226247 switch edgeTargetSafeArea. left {
@@ -230,10 +251,10 @@ extension FloatingDisplayTarget {
230251 case . activeWindow:
231252 activeWindowSafeAreaLayoutGuideConstraintLeft = leftAnchor. constraint (
232253 equalTo: _safeAreaLayoutGuide. leftAnchor)
233- containsActievWindowSafeAreaEdge = true
254+ containsActiveWindowSafeAreaEdge = true
234255 }
235256
236- if containsActievWindowSafeAreaEdge {
257+ if containsActiveWindowSafeAreaEdge {
237258
238259 NSLayoutConstraint . activate (
239260 [
@@ -248,13 +269,13 @@ extension FloatingDisplayTarget {
248269 NotificationCenter . default. addObserver (
249270 self , selector: #selector( handleInsetsUpdate) , name: SafeAreaFinder . notificationName,
250271 object: nil )
251- SafeAreaFinder . shared. start ( )
252272 }
253273 }
254274
255275 @objc private func handleInsetsUpdate( notification: Notification ) {
256276
257277 guard hasSafeAreaFinderActivated else { return }
278+ guard notification. userInfo ? [ " finder " ] as? SafeAreaFinder === safeAreaFinder else { return }
258279
259280 let insets = notification. object as! UIEdgeInsets
260281 self . activeWindowSafeAreaLayoutGuideConstraintLeft? . constant = insets. left
@@ -287,10 +308,9 @@ extension FloatingDisplayTarget {
287308 }
288309
289310 deinit {
290- Task { @MainActor [ hasSafeAreaFinderActivated] in
291- if hasSafeAreaFinderActivated {
292- SafeAreaFinder . shared. pause ( )
293- }
311+ NotificationCenter . default. removeObserver ( self )
312+ Task { @MainActor [ safeAreaFinder] in
313+ safeAreaFinder. stop ( )
294314 }
295315 }
296316 }
0 commit comments