Skip to content

Commit 72851b9

Browse files
committed
Add support for targeting a window scene
1 parent 71f78a8 commit 72851b9

File tree

3 files changed

+88
-63
lines changed

3 files changed

+88
-63
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
55

66
### Changes
77

8+
* Add `SwiftMessages.PresentationContext.windowScene` option for targeting a specific window scene.
89
* Changed the behavior of the default `presentationContext`, `.automatic`. Previously, if the root view controller was presenting, the message would only be displayed over the presented view controller if the `modalPresentationStyle` was `fullScreen` or `overFullScreen`. Now, messages are always displayed over presented view controllers.
910

1011
## 7.0.1

SwiftMessages/Presenter.swift

+74-61
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,62 @@ protocol PresenterDelegate: AnimationDelegate {
1414

1515
class Presenter: NSObject {
1616

17+
// MARK: - API
18+
19+
init(config: SwiftMessages.Config, view: UIView, delegate: PresenterDelegate) {
20+
self.config = config
21+
self.view = view
22+
self.delegate = delegate
23+
self.animator = Presenter.animator(forPresentationStyle: config.presentationStyle, delegate: delegate)
24+
if let identifiable = view as? Identifiable {
25+
id = identifiable.id
26+
} else {
27+
var mutableView = view
28+
id = withUnsafePointer(to: &mutableView) { "\($0)" }
29+
}
30+
31+
super.init()
32+
}
33+
34+
var id: String
35+
var config: SwiftMessages.Config
36+
let maskingView = MaskingView()
37+
let animator: Animator
38+
var isHiding = false
39+
let view: UIView
40+
41+
var delayShow: TimeInterval? {
42+
if case .indefinite(let opts) = config.duration { return opts.delay }
43+
return nil
44+
}
45+
46+
var showDate: CFTimeInterval?
47+
48+
/// Returns the required delay for hiding based on time shown
49+
var delayHide: TimeInterval? {
50+
if interactivelyHidden { return 0 }
51+
if case .indefinite(let opts) = config.duration, let showDate = showDate {
52+
let timeIntervalShown = CACurrentMediaTime() - showDate
53+
return max(0, opts.minimum - timeIntervalShown)
54+
}
55+
return nil
56+
}
57+
58+
var pauseDuration: TimeInterval? {
59+
let duration: TimeInterval?
60+
switch self.config.duration {
61+
case .automatic:
62+
duration = 2
63+
case .seconds(let seconds):
64+
duration = seconds
65+
case .forever, .indefinite:
66+
duration = nil
67+
}
68+
return duration
69+
}
70+
71+
// MARK: - Constants
72+
1773
enum PresentationContext {
1874
case viewController(_: Weak<UIViewController>)
1975
case view(_: Weak<UIView>)
@@ -36,29 +92,24 @@ class Presenter: NSObject {
3692
}
3793
}
3894
}
39-
40-
var config: SwiftMessages.Config
41-
let view: UIView
42-
weak var delegate: PresenterDelegate?
43-
let maskingView = MaskingView()
44-
var presentationContext = PresentationContext.viewController(Weak<UIViewController>(value: nil))
45-
let animator: Animator
4695

47-
init(config: SwiftMessages.Config, view: UIView, delegate: PresenterDelegate) {
48-
self.config = config
49-
self.view = view
50-
self.delegate = delegate
51-
self.animator = Presenter.animator(forPresentationStyle: config.presentationStyle, delegate: delegate)
52-
if let identifiable = view as? Identifiable {
53-
id = identifiable.id
54-
} else {
55-
var mutableView = view
56-
id = withUnsafePointer(to: &mutableView) { "\($0)" }
57-
}
96+
// MARK: - Variables
5897

59-
super.init()
98+
private weak var delegate: PresenterDelegate?
99+
private var presentationContext = PresentationContext.viewController(Weak<UIViewController>(value: nil))
100+
101+
@available (iOS 13.0, *)
102+
private var windowScene: UIWindowScene? {
103+
switch config.presentationContext {
104+
case .windowScene(let scene, _): return scene
105+
default: return UIApplication.shared.keyWindow?.windowScene
106+
}
60107
}
61108

109+
private var interactivelyHidden = false;
110+
111+
// MARK: - Showing and hiding
112+
62113
private static func animator(forPresentationStyle style: SwiftMessages.PresentationStyle, delegate: AnimationDelegate) -> Animator {
63114
switch style {
64115
case .top:
@@ -73,44 +124,6 @@ class Presenter: NSObject {
73124
}
74125
}
75126

76-
var id: String
77-
78-
var pauseDuration: TimeInterval? {
79-
let duration: TimeInterval?
80-
switch self.config.duration {
81-
case .automatic:
82-
duration = 2
83-
case .seconds(let seconds):
84-
duration = seconds
85-
case .forever, .indefinite:
86-
duration = nil
87-
}
88-
return duration
89-
}
90-
91-
var showDate: CFTimeInterval?
92-
93-
private var interactivelyHidden = false;
94-
95-
var delayShow: TimeInterval? {
96-
if case .indefinite(let opts) = config.duration { return opts.delay }
97-
return nil
98-
}
99-
100-
/// Returns the required delay for hiding based on time shown
101-
var delayHide: TimeInterval? {
102-
if interactivelyHidden { return 0 }
103-
if case .indefinite(let opts) = config.duration, let showDate = showDate {
104-
let timeIntervalShown = CACurrentMediaTime() - showDate
105-
return max(0, opts.minimum - timeIntervalShown)
106-
}
107-
return nil
108-
}
109-
110-
/*
111-
MARK: - Showing and hiding
112-
*/
113-
114127
func show(completion: @escaping AnimationCompletion) throws {
115128
try presentationContext = getPresentationContext()
116129
install()
@@ -174,8 +187,6 @@ class Presenter: NSObject {
174187
UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: focus)
175188
}
176189

177-
var isHiding = false
178-
179190
func hide(animated: Bool, completion: @escaping AnimationCompletion) {
180191
isHiding = true
181192
self.config.eventListeners.forEach { $0(.willHide) }
@@ -308,6 +319,9 @@ class Presenter: NSObject {
308319
case .window(let level):
309320
let viewController = newWindowViewController(level)
310321
return .viewController(Weak(value: viewController))
322+
case .windowScene(_, let level):
323+
let viewController = newWindowViewController(level)
324+
return .viewController(Weak(value: viewController))
311325
case .viewController(let viewController):
312326
let viewController = viewController.sm_selectPresentationContextBottomUp(config)
313327
return .viewController(Weak(value: viewController))
@@ -409,8 +423,7 @@ class Presenter: NSObject {
409423
guard let containerView = presentationContext.viewValue() else { return }
410424
if let windowViewController = presentationContext.viewControllerValue() as? WindowViewController {
411425
if #available(iOS 13, *) {
412-
let scene = UIApplication.shared.keyWindow?.windowScene
413-
windowViewController.install(becomeKey: becomeKeyWindow, scene: scene)
426+
windowViewController.install(becomeKey: becomeKeyWindow, scene: windowScene)
414427
} else {
415428
windowViewController.install(becomeKey: becomeKeyWindow)
416429
}

SwiftMessages/SwiftMessages.swift

+13-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,18 @@ open class SwiftMessages {
7070
to hide it.
7171
*/
7272
case window(windowLevel: UIWindow.Level)
73-
73+
74+
/**
75+
Displays the message in a new window, at the specified window level,
76+
in the specified window scene. SwiftMessages automatically increases the top margins
77+
of any message view that adopts the `MarginInsetting` protocol (as `MessageView` does)
78+
to account for the status bar. As of iOS 13, windows can no longer cover the
79+
status bar. The only alternative is to set `Config.prefersStatusBarHidden = true`
80+
to hide it.
81+
*/
82+
@available(iOS 13.0, *)
83+
case windowScene(_: UIWindowScene, windowLevel: UIWindow.Level)
84+
7485
/**
7586
Displays the message view under navigation bars and tab bars if an
7687
appropriate one is found using the given view controller as a starting
@@ -79,7 +90,7 @@ open class SwiftMessages {
7990
for targeted placement in a view controller heirarchy.
8091
*/
8192
case viewController(_: UIViewController)
82-
93+
8394
/**
8495
Displays the message view in the given container view.
8596
*/

0 commit comments

Comments
 (0)