From b53a09ad75386739edd00f42f8609065ddae8107 Mon Sep 17 00:00:00 2001 From: xaoxuu Date: Sun, 6 Aug 2023 14:36:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=82=E9=85=8DiPad=E5=A4=9A=E7=AA=97?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PHDemo/PHDemo/Extensions.swift | 4 +- PHDemo/PHDemo/Info.plist | 2 +- PHDemo/PHDemo/ListVC.swift | 2 + Package.swift | 2 +- Sources/ProHUD/Alert/AlertDefaultLayout.swift | 6 +- Sources/ProHUD/Alert/AlertManager.swift | 53 +++++---- Sources/ProHUD/Alert/AlertWindow.swift | 38 +++++-- .../ProHUD/Core/Models/Configuration.swift | 34 ++---- Sources/ProHUD/Core/Protocols/HUD.swift | 10 +- Sources/ProHUD/Core/Utils/AppContext.swift | 105 +++++++++++++----- Sources/ProHUD/Core/Utils/LayerExts.swift | 4 +- Sources/ProHUD/Core/Utils/Utils.swift | 8 +- Sources/ProHUD/Core/Views/Window.swift | 1 - Sources/ProHUD/Sheet/SheetManager.swift | 2 +- Sources/ProHUD/Sheet/SheetWindow.swift | 32 ++++-- Sources/ProHUD/Toast/ToastManager.swift | 2 +- Sources/ProHUD/Toast/ToastWindow.swift | 41 ++++--- 17 files changed, 218 insertions(+), 128 deletions(-) diff --git a/PHDemo/PHDemo/Extensions.swift b/PHDemo/PHDemo/Extensions.swift index 2309db6..290454b 100644 --- a/PHDemo/PHDemo/Extensions.swift +++ b/PHDemo/PHDemo/Extensions.swift @@ -51,10 +51,8 @@ extension CALayer { var cornerRadiusWithContinuous: CGFloat { set { cornerRadius = newValue - if #available(iOS 13.0, *) { + if cornerCurve != .continuous { cornerCurve = .continuous - } else { - // Fallback on earlier versions } } get { cornerRadius } diff --git a/PHDemo/PHDemo/Info.plist b/PHDemo/PHDemo/Info.plist index dd3c9af..8963569 100644 --- a/PHDemo/PHDemo/Info.plist +++ b/PHDemo/PHDemo/Info.plist @@ -5,7 +5,7 @@ UIApplicationSceneManifest UIApplicationSupportsMultipleScenes - + UISceneConfigurations UIWindowSceneSessionRoleApplication diff --git a/PHDemo/PHDemo/ListVC.swift b/PHDemo/PHDemo/ListVC.swift index 5b199d7..d83938a 100644 --- a/PHDemo/PHDemo/ListVC.swift +++ b/PHDemo/PHDemo/ListVC.swift @@ -6,6 +6,7 @@ // import UIKit +import ProHUD class ListVC: UITableViewController { @@ -46,6 +47,7 @@ class ListVC: UITableViewController { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) + AppContext.workspace = self list.sections[indexPath.section].rows[indexPath.row].action() } diff --git a/Package.swift b/Package.swift index 1a5bea2..2ad0476 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,7 @@ import PackageDescription let package = Package( name: "ProHUD", - platforms: [.iOS(.v10)], + platforms: [.iOS(.v13)], products: [ .library(name: "ProHUD", targets: ["ProHUD"]), ], diff --git a/Sources/ProHUD/Alert/AlertDefaultLayout.swift b/Sources/ProHUD/Alert/AlertDefaultLayout.swift index 9e35489..f8286d8 100644 --- a/Sources/ProHUD/Alert/AlertDefaultLayout.swift +++ b/Sources/ProHUD/Alert/AlertDefaultLayout.swift @@ -68,7 +68,8 @@ extension Alert: DefaultLayout { if contentView.superview != view { view.insertSubview(contentView, at: 0) } - if config.enableShadow && AlertWindow.alerts.count > 0 { + let alerts = window?.alerts ?? [] + if config.enableShadow && alerts.count > 0 { contentView.clipsToBounds = false contentView.layer.shadowRadius = 4 contentView.layer.shadowOpacity = 0.08 @@ -242,7 +243,8 @@ extension Alert { public override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - if config.enableShadow && AlertWindow.alerts.count > 1 { + let alerts = window?.alerts ?? [] + if config.enableShadow && alerts.count > 1 { contentView.layer.shadowPath = UIBezierPath.init(rect: contentView.bounds).cgPath } } diff --git a/Sources/ProHUD/Alert/AlertManager.swift b/Sources/ProHUD/Alert/AlertManager.swift index b71f0a1..ec07a4e 100644 --- a/Sources/ProHUD/Alert/AlertManager.swift +++ b/Sources/ProHUD/Alert/AlertManager.swift @@ -8,12 +8,14 @@ import UIKit extension Alert: HUD { - + public func push(scene: UIWindowScene?) { + push() + } public func push() { - guard AlertWindow.alerts.contains(self) == false else { + let window = createAttachedWindowIfNotExists() + guard window.alerts.contains(self) == false else { return } - let window = attachedWindow view.transform = .init(scaleX: 1.2, y: 1.2) view.alpha = 0 navEvents[.onViewWillAppear]?(self) @@ -32,13 +34,13 @@ extension Alert: HUD { } completion: { done in self.navEvents[.onViewDidAppear]?(self) } - AlertWindow.alerts.append(self) - Alert.updateAlertsLayout() + window.alerts.append(self) + Alert.updateAlertsLayout(alerts: window.alerts) } public func pop() { navEvents[.onViewWillDisappear]?(self) - let window = attachedWindow + let window = window ?? createAttachedWindowIfNotExists() Alert.removeAlert(alert: self) let duration = config.animateDurationForBuildOut ?? config.animateDurationForBuildOutByDefault UIView.animateEaseOut(duration: duration) { @@ -50,13 +52,14 @@ extension Alert: HUD { self.navEvents[.onViewDidDisappear]?(self) } // hide window - let count = AlertWindow.alerts.count - if count == 0 && AlertWindow.current != nil { + let count = window.alerts.count + if count == 0 { UIView.animateEaseOut(duration: duration) { window.backgroundView.alpha = 0 } completion: { done in - if AlertWindow.alerts.count == 0 { - AlertWindow.current = nil + // 此时不能用self.window,因为alert已经释放掉了 + if window.alerts.count == 0, let scene = window.windowScene { + AppContext.alertWindow[scene] = nil } } } @@ -72,7 +75,7 @@ public extension Alert { /// - handler: 实例创建代码 static func lazyPush(identifier: String? = nil, file: String = #file, line: Int = #line, handler: @escaping (_ alert: Alert) -> Void, onExists: ((_ alert: Alert) -> Void)? = nil) { let id = identifier ?? (file + "#\(line)") - if let vc = AlertWindow.alerts.last(where: { $0.identifier == id }) { + if let vc = find(identifier: id).last { vc.update(handler: onExists ?? handler) } else { Alert { alert in @@ -96,7 +99,7 @@ public extension Alert { /// - Parameter identifier: 唯一标识符 /// - Returns: HUD实例 @discardableResult static func find(identifier: String, update handler: ((_ alert: Alert) -> Void)? = nil) -> [Alert] { - let arr = AlertWindow.alerts.filter({ $0.identifier == identifier }) + let arr = AppContext.alertWindow.values.flatMap({ $0.alerts }).filter({ $0.identifier == identifier }) if let handler = handler { arr.forEach({ $0.update(handler: handler) }) } @@ -106,8 +109,8 @@ public extension Alert { } fileprivate extension Alert { - static func updateAlertsLayout() { - for (i, a) in AlertWindow.alerts.reversed().enumerated() { + static func updateAlertsLayout(alerts: [Alert]) { + for (i, a) in alerts.reversed().enumerated() { let scale = CGFloat(pow(0.9, CGFloat(i))) UIView.animate(withDuration: 1.8, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0.5, options: [.allowUserInteraction, .curveEaseInOut], animations: { let y = 0 - a.config.stackDepth * CGFloat(i) * CGFloat(pow(0.85, CGFloat(i))) @@ -118,25 +121,29 @@ fileprivate extension Alert { } } - var attachedWindow: AlertWindow { - AlertWindow.attachedWindow(config: config) + func createAttachedWindowIfNotExists() -> AlertWindow { + AlertWindow.createAttachedWindowIfNotExists(config: config) } static func removeAlert(alert: Alert) { - if AlertWindow.alerts.count > 1 { - for (i, a) in AlertWindow.alerts.enumerated() { + guard var alerts = alert.window?.alerts else { + return + } + if alerts.count > 1 { + for (i, a) in alerts.enumerated() { if a == alert { - if i < AlertWindow.alerts.count { - AlertWindow.alerts.remove(at: i) + if i < alerts.count { + alerts.remove(at: i) } } } - updateAlertsLayout() - } else if AlertWindow.alerts.count == 1 { - AlertWindow.alerts.removeAll() + updateAlertsLayout(alerts: alerts) + } else if alerts.count == 1 { + alerts.removeAll() } else { print("‼️代码漏洞:已经没有alert了") } + alert.window?.alerts = alerts } } diff --git a/Sources/ProHUD/Alert/AlertWindow.swift b/Sources/ProHUD/Alert/AlertWindow.swift index 3a144a7..29e43e6 100644 --- a/Sources/ProHUD/Alert/AlertWindow.swift +++ b/Sources/ProHUD/Alert/AlertWindow.swift @@ -7,29 +7,43 @@ import UIKit +extension Alert { + var window: AlertWindow? { + get { + guard let windowScene = windowScene else { + return nil + } + return AppContext.alertWindow[windowScene] + } + set { + guard let windowScene = windowScene else { + return + } + AppContext.alertWindow[windowScene] = newValue + } + } +} + class AlertWindow: Window { - static var current: AlertWindow? - - static var alerts = [Alert]() + var alerts: [Alert] = [] override var usingBackground: Bool { true } - static func attachedWindow(config: Configuration) -> AlertWindow { - if let w = AlertWindow.current { + static func createAttachedWindowIfNotExists(config: Configuration) -> AlertWindow { + let windowScene = AppContext.windowScene + if let windowScene = windowScene, let w = AppContext.alertWindow[windowScene] { return w } let w: AlertWindow - if #available(iOS 13.0, *) { - if let scene = AppContext.windowScene { - w = .init(windowScene: scene) - } else { - w = .init(frame: AppContext.appBounds) - } + if let scene = windowScene { + w = .init(windowScene: scene) } else { w = .init(frame: AppContext.appBounds) } - AlertWindow.current = w + if let windowScene = windowScene { + AppContext.alertWindow[windowScene] = w + } // 比原生alert层级低一点 w.windowLevel = .init(rawValue: UIWindow.Level.alert.rawValue - 1) return w diff --git a/Sources/ProHUD/Core/Models/Configuration.swift b/Sources/ProHUD/Core/Models/Configuration.swift index 7919937..c9c46f3 100644 --- a/Sources/ProHUD/Core/Models/Configuration.swift +++ b/Sources/ProHUD/Core/Models/Configuration.swift @@ -13,36 +13,26 @@ public class Configuration: NSObject { public static var enablePrint = true public lazy var dynamicBackgroundColor: UIColor = { - if #available(iOS 13.0, *) { - let color = UIColor { (traitCollection: UITraitCollection) -> UIColor in - if traitCollection.userInterfaceStyle == .dark { - return .init(white: 0.15, alpha: 1) - } else { - return .init(white: 1, alpha: 1) - } - } - return color + let color = UIColor { (traitCollection: UITraitCollection) -> UIColor in + if traitCollection.userInterfaceStyle == .dark { + return .init(white: 0.15, alpha: 1) } else { - // Fallback on earlier versions + return .init(white: 1, alpha: 1) + } } - return .init(white: 1, alpha: 1) + return color }() /// 动态颜色(适配iOS13) public lazy var dynamicTextColor: UIColor = { - if #available(iOS 13.0, *) { - let color = UIColor { (traitCollection: UITraitCollection) -> UIColor in - if traitCollection.userInterfaceStyle == .dark { - return .init(white: 1, alpha: 1) - } else { - return .init(white: 0.1, alpha: 1) - } + let color = UIColor { (traitCollection: UITraitCollection) -> UIColor in + if traitCollection.userInterfaceStyle == .dark { + return .init(white: 1, alpha: 1) + } else { + return .init(white: 0.1, alpha: 1) } - return color - } else { - // Fallback on earlier versions } - return .init(white: 0.1, alpha: 1) + return color }() /// 主标签文本颜色 diff --git a/Sources/ProHUD/Core/Protocols/HUD.swift b/Sources/ProHUD/Core/Protocols/HUD.swift index ba50838..66e5b98 100644 --- a/Sources/ProHUD/Core/Protocols/HUD.swift +++ b/Sources/ProHUD/Core/Protocols/HUD.swift @@ -5,9 +5,17 @@ // Created by xaoxuu on 2022/8/29. // -import Foundation +import UIKit public protocol HUD { func push() + func push(workspace: Workspace?) func pop() } + +public extension HUD { + func push(workspace: Workspace?) { + AppContext.workspace = workspace + push() + } +} diff --git a/Sources/ProHUD/Core/Utils/AppContext.swift b/Sources/ProHUD/Core/Utils/AppContext.swift index 110f8e2..07ca7b5 100644 --- a/Sources/ProHUD/Core/Utils/AppContext.swift +++ b/Sources/ProHUD/Core/Utils/AppContext.swift @@ -7,41 +7,85 @@ import UIKit +public protocol Workspace {} + +extension UIWindowScene: Workspace {} +extension UIView: Workspace {} +extension UIViewController: Workspace {} + +extension Workspace { + var windowScene: UIWindowScene? { + if let self = self as? UIWindowScene { + return self + } else if let self = self as? UIWindow { + return self.windowScene + } else if let self = self as? UIView { + return self.window?.windowScene + } else if let self = self as? UIViewController { + return self.view.window?.windowScene + } + return nil + } +} + public struct AppContext { - @available(iOS 13.0, *) private static var storedAppWindowScene: UIWindowScene? - private static var storedAppWindow: UIWindow? + /// 一个scene关联一个toast + static var toastWindows: [UIWindowScene: [ToastWindow]] = [:] + static var alertWindow: [UIWindowScene: AlertWindow] = [:] + static var sheetWindows: [UIWindowScene: [SheetWindow]] = [:] - private init() {} + static var current: AppContext? { + guard let windowScene = windowScene else { return nil } + if let ctx = allContexts[windowScene] { + return ctx + } else { + let ctx: AppContext = .init(windowScene: windowScene) + allContexts[windowScene] = ctx + return ctx + } + } + static var allContexts = [UIWindowScene: AppContext]() + private let windowScene: UIWindowScene + + private init(windowScene: UIWindowScene) { + self.windowScene = windowScene + } + + /// 单窗口应用无需设置,多窗口应用需要指定显示到哪个windowScene上 + /// workspace可以是windowScene/window/view/viewController + public static var workspace: Workspace? { + get { windowScene } + set { + windowScene = newValue?.windowScene + } + } } -public extension AppContext { +extension AppContext { - @available(iOS 13.0, *) + static var foregroundActiveWindowScenes: [UIWindowScene] { + return UIApplication.shared.connectedScenes.compactMap({ $0 as? UIWindowScene }).filter({ $0.activationState == .foregroundActive }) + } + + /// 如果设置了workspace,就是workspace所对应的windowScene,否则就是最后一个打开的应用程序窗口的windowScene static var windowScene: UIWindowScene? { set { storedAppWindowScene = newValue } get { if let ws = storedAppWindowScene { return ws } else { - return UIApplication.shared.connectedScenes.first(where: { scene in - guard let ws = scene as? UIWindowScene else { return false } - return ws.activationState == .foregroundActive - }) as? UIWindowScene + return foregroundActiveWindowScenes.last } } } /// 所有的窗口 static var windows: [UIWindow] { - if #available(iOS 13.0, *) { - return windowScene?.windows ?? UIApplication.shared.windows - } else { - return UIApplication.shared.windows - } + windowScene?.windows ?? UIApplication.shared.windows } /// 可见的窗口 @@ -51,28 +95,31 @@ public extension AppContext { /// App主程序窗口 static var appWindow: UIWindow? { - get { - if let w = storedAppWindow { - return w - } else { - return visibleWindows.filter { window in - return "\(type(of: window))" == "UIWindow" && window.windowLevel == .normal - }.first - } - } - set { storedAppWindow = newValue } + visibleWindows.filter { window in + return "\(type(of: window))" == "UIWindow" && window.windowLevel == .normal + }.first } /// App主程序窗口的尺寸 static var appBounds: CGRect { - if #available(iOS 13.0, *) { - return appWindow?.bounds ?? UIScreen.main.bounds - } else { - return UIScreen.main.bounds - } + appWindow?.bounds ?? UIScreen.main.bounds } /// App主程序窗口的安全边距 static var safeAreaInsets: UIEdgeInsets { appWindow?.safeAreaInsets ?? .zero } } + +// MARK: - instance manage + +extension AppContext { + var sheetWindows: [SheetWindow] { + Self.sheetWindows[windowScene] ?? [] + } +} + +extension AppContext { + var toastWindows: [ToastWindow] { + Self.toastWindows[windowScene] ?? [] + } +} diff --git a/Sources/ProHUD/Core/Utils/LayerExts.swift b/Sources/ProHUD/Core/Utils/LayerExts.swift index 9cf4a54..0fe7d95 100644 --- a/Sources/ProHUD/Core/Utils/LayerExts.swift +++ b/Sources/ProHUD/Core/Utils/LayerExts.swift @@ -13,10 +13,8 @@ extension CALayer { var cornerRadiusWithContinuous: CGFloat { set { cornerRadius = newValue - if #available(iOS 13.0, *) { + if cornerCurve != .continuous { cornerCurve = .continuous - } else { - // Fallback on earlier versions } } get { cornerRadius } diff --git a/Sources/ProHUD/Core/Utils/Utils.swift b/Sources/ProHUD/Core/Utils/Utils.swift index bef98ce..2abc835 100644 --- a/Sources/ProHUD/Core/Utils/Utils.swift +++ b/Sources/ProHUD/Core/Utils/Utils.swift @@ -9,11 +9,7 @@ import UIKit extension UIImage { public convenience init?(inProHUD named: String) { - if #available(iOS 13.0, *) { - self.init(named: named, in: .module, with: .none) - } else { - self.init(named: named) - } + self.init(named: named, in: .module, with: .none) } } @@ -24,7 +20,7 @@ internal var isPortrait: Bool { return true } if UIDevice.current.userInterfaceIdiom == .phone { - if UIApplication.shared.statusBarOrientation.isPortrait { + if AppContext.windowScene?.interfaceOrientation.isPortrait == true { return true } } diff --git a/Sources/ProHUD/Core/Views/Window.swift b/Sources/ProHUD/Core/Views/Window.swift index 12da8c8..b072e36 100644 --- a/Sources/ProHUD/Core/Views/Window.swift +++ b/Sources/ProHUD/Core/Views/Window.swift @@ -41,7 +41,6 @@ class Window: UIWindow { rootViewController = vc } - @available(iOS 13.0, *) override init(windowScene: UIWindowScene) { super.init(windowScene: windowScene) setup() diff --git a/Sources/ProHUD/Sheet/SheetManager.swift b/Sources/ProHUD/Sheet/SheetManager.swift index 585b3bf..84ad844 100644 --- a/Sources/ProHUD/Sheet/SheetManager.swift +++ b/Sources/ProHUD/Sheet/SheetManager.swift @@ -51,7 +51,7 @@ public extension Sheet { /// - Parameter identifier: 唯一标识符 /// - Returns: HUD实例 @discardableResult static func find(identifier: String, update handler: ((_ sheet: Sheet) -> Void)? = nil) -> [Sheet] { - let arr = SheetWindow.windows.compactMap({ $0.sheet }).filter({ $0.identifier == identifier }) + let arr = AppContext.sheetWindows.values.flatMap({ $0 }).compactMap({ $0.sheet }).filter({ $0.identifier == identifier }) if let handler = handler { arr.forEach({ $0.update(handler: handler) }) } diff --git a/Sources/ProHUD/Sheet/SheetWindow.swift b/Sources/ProHUD/Sheet/SheetWindow.swift index 5f6cc16..ba3f625 100644 --- a/Sources/ProHUD/Sheet/SheetWindow.swift +++ b/Sources/ProHUD/Sheet/SheetWindow.swift @@ -1,5 +1,5 @@ // -// File.swift +// SheetWindow.swift // // // Created by xaoxuu on 2022/9/8. @@ -7,20 +7,30 @@ import UIKit + +private extension Sheet { + func getContextWindows() -> [SheetWindow] { + guard let windowScene = windowScene else { + return [] + } + return AppContext.sheetWindows[windowScene] ?? [] + } + func setContextWindows(_ windows: [SheetWindow]) { + guard let windowScene = windowScene else { + return + } + AppContext.sheetWindows[windowScene] = windows + } +} + class SheetWindow: Window { - static var windows = [SheetWindow]() - var sheet: Sheet init(sheet: Sheet) { self.sheet = sheet - if #available(iOS 13.0, *) { - if let scene = AppContext.windowScene { - super.init(windowScene: scene) - } else { - super.init(frame: AppContext.appBounds) - } + if let scene = AppContext.windowScene { + super.init(windowScene: scene) } else { super.init(frame: AppContext.appBounds) } @@ -36,6 +46,7 @@ class SheetWindow: Window { static func push(sheet: Sheet) { let isNew: Bool let window: SheetWindow + var windows = AppContext.current?.sheetWindows ?? [] if let w = windows.first(where: { $0.sheet == sheet }) { isNew = false window = w @@ -46,6 +57,7 @@ class SheetWindow: Window { window.rootViewController = sheet if windows.contains(window) == false { windows.append(window) + sheet.setContextWindows(windows) } if isNew { sheet.navEvents[.onViewWillAppear]?(sheet) @@ -58,6 +70,7 @@ class SheetWindow: Window { } static func pop(sheet: Sheet) { + var windows = sheet.getContextWindows() guard let window = windows.first(where: { $0.sheet == sheet }) else { return } @@ -72,6 +85,7 @@ class SheetWindow: Window { } else { consolePrint("‼️代码漏洞:已经没有sheet了") } + sheet.setContextWindows(windows) } } } diff --git a/Sources/ProHUD/Toast/ToastManager.swift b/Sources/ProHUD/Toast/ToastManager.swift index 569d860..0607fc5 100644 --- a/Sources/ProHUD/Toast/ToastManager.swift +++ b/Sources/ProHUD/Toast/ToastManager.swift @@ -51,7 +51,7 @@ public extension Toast { /// - Parameter identifier: 唯一标识符 /// - Returns: HUD实例 @discardableResult static func find(identifier: String, update handler: ((_ toast: Toast) -> Void)? = nil) -> [Toast] { - let arr = ToastWindow.windows.compactMap({ $0.toast }).filter({ $0.identifier == identifier }) + let arr = AppContext.toastWindows.values.flatMap({ $0 }).compactMap({ $0.toast }).filter({ $0.identifier == identifier }) if let handler = handler { arr.forEach({ $0.update(handler: handler) }) } diff --git a/Sources/ProHUD/Toast/ToastWindow.swift b/Sources/ProHUD/Toast/ToastWindow.swift index c6b4dc2..e6d6d2b 100644 --- a/Sources/ProHUD/Toast/ToastWindow.swift +++ b/Sources/ProHUD/Toast/ToastWindow.swift @@ -7,10 +7,23 @@ import UIKit +private extension Toast { + func getContextWindows() -> [ToastWindow] { + guard let windowScene = windowScene else { + return [] + } + return AppContext.toastWindows[windowScene] ?? [] + } + func setContextWindows(_ windows: [ToastWindow]) { + guard let windowScene = windowScene else { + return + } + AppContext.toastWindows[windowScene] = windows + } +} + class ToastWindow: Window { - static var windows = [ToastWindow]() - var toast: Toast var maxY = CGFloat(0) @@ -18,9 +31,7 @@ class ToastWindow: Window { init(toast: Toast) { self.toast = toast super.init(frame: .zero) - if #available(iOS 13.0, *) { - windowScene = AppContext.windowScene - } + windowScene = AppContext.windowScene toast.window = self windowLevel = .init(rawValue: UIWindow.Level.alert.rawValue + 1000) layer.shadowRadius = 8 @@ -41,6 +52,7 @@ class ToastWindow: Window { static func push(toast: Toast) { let isNew: Bool let window: ToastWindow + var windows = AppContext.current?.toastWindows ?? [] if let w = windows.first(where: { $0.toast == toast }) { isNew = false window = w @@ -64,8 +76,9 @@ class ToastWindow: Window { window.rootViewController = toast // 此时toast.view.frame.size会自动更新为window.frame.size if windows.contains(window) == false { windows.append(window) + toast.setContextWindows(windows) } - updateToastWindowsLayout() + updateToastWindowsLayout(windows: windows) if isNew { window.transform = .init(translationX: 0, y: -window.frame.maxY) UIView.animateEaseOut(duration: config.animateDurationForBuildInByDefault) { @@ -80,24 +93,26 @@ class ToastWindow: Window { } static func pop(toast: Toast) { + var windows = toast.getContextWindows() guard let window = windows.first(where: { $0.toast == toast }) else { return } if windows.count > 1 { windows.removeAll { $0 == window } - updateToastWindowsLayout() + updateToastWindowsLayout(windows: windows) } else if windows.count == 1 { windows.removeAll() } else { consolePrint("‼️代码漏洞:已经没有toast了") } toast.vm.duration = nil + toast.setContextWindows(windows) UIView.animateEaseOut(duration: toast.config.animateDurationForBuildOutByDefault) { window.transform = .init(translationX: 0, y: 0-20-window.maxY) } completion: { done in - window.toast.view.removeFromSuperview() - window.toast.removeFromParent() - window.toast.navEvents[.onViewDidDisappear]?(window.toast) + toast.view.removeFromSuperview() + toast.removeFromParent() + toast.navEvents[.onViewDidDisappear]?(toast) } } @@ -108,7 +123,7 @@ fileprivate var updateToastsLayoutWorkItem: DispatchWorkItem? fileprivate extension ToastWindow { - static func setToastWindowsLayout() { + static func setToastWindowsLayout(windows: [ToastWindow]) { for (i, window) in windows.enumerated() { let config = window.toast.config var y = window.frame.origin.y @@ -128,10 +143,10 @@ fileprivate extension ToastWindow { } } - static func updateToastWindowsLayout() { + static func updateToastWindowsLayout(windows: [ToastWindow]) { updateToastsLayoutWorkItem?.cancel() updateToastsLayoutWorkItem = DispatchWorkItem { - setToastWindowsLayout() + setToastWindowsLayout(windows: windows) } DispatchQueue.main.asyncAfter(deadline: .now()+0.001, execute: updateToastsLayoutWorkItem!) }