From 4cebb3fc72e820662354b2ebdc6d784ce784fac4 Mon Sep 17 00:00:00 2001 From: xaoxuu Date: Thu, 8 Aug 2019 11:09:22 +0800 Subject: [PATCH] update --- ProHUD/Alert/AlertController.swift | 217 +++++++------------- ProHUD/Alert/AlertModel.swift | 2 +- ProHUD/Alert/AlertView.swift | 2 +- ProHUD/Guard/GuardController.swift | 39 ++-- ProHUD/Guard/GuardView.swift | 2 +- ProHUD/ProHUD.swift | 8 +- ProHUD/Toast/ToastController.swift | 309 ++++++++++++----------------- ProHUD/Toast/ToastModel.swift | 2 +- 8 files changed, 224 insertions(+), 357 deletions(-) diff --git a/ProHUD/Alert/AlertController.swift b/ProHUD/Alert/AlertController.swift index c85e921..2c089b3 100644 --- a/ProHUD/Alert/AlertController.swift +++ b/ProHUD/Alert/AlertController.swift @@ -9,9 +9,15 @@ import UIKit import SnapKit +public typealias Alert = ProHUD.Alert + public extension ProHUD { class Alert: HUDController { + internal static var alerts = [Alert]() + + internal static var alertWindow: UIWindow? + /// 内容视图 public var contentView = BlurView() @@ -57,14 +63,14 @@ public extension ProHUD { /// - Parameter title: 标题 /// - Parameter message: 内容 /// - Parameter icon: 图标 - public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil) { + public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil, actions: ((Alert) -> Void)? = nil) { self.init() view.tintColor = cfg.alert.tintColor model.scene = scene model.title = title model.message = message model.icon = icon - + actions?(self) willLayoutSubviews() } @@ -76,20 +82,40 @@ public extension ProHUD { // MARK: - 实例函数 -public extension ProHUD.Alert { +public extension Alert { // MARK: 生命周期函数 /// 推入屏幕 - @discardableResult func push() -> ProHUD.Alert { - return ProHUD.push(self) + @discardableResult func push() -> Alert { + let hud = ProHUD.shared + if Alert.alerts.contains(self) == false { + let window = Alert.getAlertWindow(self) + window.makeKeyAndVisible() + window.resignKey() + window.addSubview(view) + view.transform = .init(scaleX: 1.2, y: 1.2) + view.alpha = 0 + UIView.animateForAlertBuildIn { + self.view.transform = .identity + self.view.alpha = 1 + window.backgroundColor = window.backgroundColor?.withAlphaComponent(0.6) + } + Alert.alerts.append(self) + } + Alert.updateAlertsLayout() + + // setup duration + if let _ = model.duration, model.durationBlock == nil { + duration(model.duration) + } + return self } /// 弹出屏幕 func pop() { - let hud = ProHUD.shared - let window = hud.getAlertWindow(self) - hud.removeItemFromArray(alert: self) + let window = Alert.getAlertWindow(self) + Alert.removeItemFromArray(alert: self) UIView.animateForAlertBuildOut(animations: { self.view.alpha = 0 self.view.transform = .init(scaleX: 1.08, y: 1.08) @@ -98,12 +124,12 @@ public extension ProHUD.Alert { self.removeFromParent() } // hide window - let count = hud.alerts.count - if count == 0 && hud.alertWindow != nil { + let count = Alert.alerts.count + if count == 0 && Alert.alertWindow != nil { UIView.animateForAlertBuildOut(animations: { window.backgroundColor = window.backgroundColor?.withAlphaComponent(0) }) { (done) in - hud.alertWindow = nil + Alert.alertWindow = nil } } } @@ -114,39 +140,32 @@ public extension ProHUD.Alert { /// 添加按钮 /// - Parameter style: 样式 /// - Parameter text: 标题 - /// - Parameter action: 事件 - @discardableResult func add(action style: UIAlertAction.Style, title: String?, handler: (() -> Void)?) -> ProHUD.Alert { - if let btn = privAddButton(custom: Button.actionButton(title: title), action: handler) as? Button { - btn.update(style: style) + /// - Parameter handler: 事件处理 + @discardableResult func add(action style: UIAlertAction.Style, title: String?, handler: (() -> Void)?) -> UIButton { + let btn = privAddButton(custom: Button.actionButton(title: title), action: handler) + if let b = btn as? Button { + b.update(style: style) } - return self - } - - /// 添加按钮 - /// - Parameter button: 按钮 - /// - Parameter action: 事件 - @discardableResult func add(button: UIButton, action: (() -> Void)?) -> ProHUD.Alert { - privAddButton(custom: button, action: action) - return self + return btn } /// 最小化事件 /// - Parameter callback: 事件回调 - @discardableResult func didForceQuit(_ callback: (() -> Void)?) -> ProHUD.Alert { + @discardableResult func didForceQuit(_ callback: (() -> Void)?) -> Alert { model.forceQuitCallback = callback return self } /// 消失事件 /// - Parameter callback: 事件回调 - @discardableResult func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Alert { + @discardableResult func didDisappear(_ callback: (() -> Void)?) -> Alert { disappearCallback = callback return self } /// 设置持续时间 /// - Parameter duration: 持续时间 - @discardableResult func duration(_ duration: TimeInterval?) -> ProHUD.Alert { + @discardableResult func duration(_ duration: TimeInterval?) -> Alert { model.setupDuration(duration: duration) { [weak self] in self?.pop() } @@ -157,7 +176,7 @@ public extension ProHUD.Alert { /// - Parameter scene: 场景 /// - Parameter title: 标题 /// - Parameter message: 正文 - @discardableResult func update(scene: Scene, title: String?, message: String?) -> ProHUD.Alert { + @discardableResult func update(scene: Scene, title: String?, message: String?) -> Alert { model.scene = scene model.title = title model.message = message @@ -167,7 +186,7 @@ public extension ProHUD.Alert { /// 更新图标 /// - Parameter icon: 图标 - @discardableResult func update(icon: UIImage?) -> ProHUD.Alert { + @discardableResult func update(icon: UIImage?) -> Alert { model.icon = icon cfg.alert.reloadData(self) imageView?.layer.removeAllAnimations() @@ -179,36 +198,23 @@ public extension ProHUD.Alert { /// - Parameter style: 样式 /// - Parameter title: 标题 /// - Parameter action: 事件 - @discardableResult func update(action index: Int, style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> ProHUD.Alert { - return update(action: index, button: { (btn) in + @discardableResult func update(action index: Int, style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> Alert { + if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton { btn.setTitle(title, for: .normal) if let b = btn as? Button { b.update(style: style) } btn.layoutIfNeeded() - }, action: action) - } - - /// 更新按钮 - /// - Parameter index: 索引 - /// - Parameter button: 按钮 - /// - Parameter action: 事件 - @discardableResult func update(action index: Int, button: (UIButton) -> Void, action: (() -> Void)? = nil) -> ProHUD.Alert { - if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton { - button(btn) if let ac = action { addTouchUpAction(for: btn, action: ac) } } - UIView.animateForAlert { - self.view.layoutIfNeeded() - } return self } /// 移除按钮 /// - Parameter index: 索引 - @discardableResult func remove(action index: Int...) -> ProHUD.Alert { + @discardableResult func remove(action index: Int...) -> Alert { for (i, idx) in index.enumerated() { privRemoveAction(index: idx-i) } @@ -218,130 +224,54 @@ public extension ProHUD.Alert { } +// MARK: 类函数 -// MARK: - 实例函数 - -public extension ProHUD { - - /// 推入屏幕 - /// - Parameter alert: 实例 - @discardableResult func push(_ alert: Alert) -> Alert { - if alerts.contains(alert) == false { - let window = getAlertWindow(alert) - window.makeKeyAndVisible() - window.resignKey() - window.addSubview(alert.view) - alert.view.transform = .init(scaleX: 1.2, y: 1.2) - alert.view.alpha = 0 - UIView.animateForAlertBuildIn { - alert.view.transform = .identity - alert.view.alpha = 1 - window.backgroundColor = window.backgroundColor?.withAlphaComponent(0.6) - } - alerts.append(alert) - } - updateAlertsLayout() - - // setup duration - if let _ = alert.model.duration, alert.model.durationBlock == nil { - alert.duration(alert.model.duration) - } - return alert - } +public extension Alert { /// 推入屏幕 /// - Parameter alert: 场景 /// - Parameter title: 标题 /// - Parameter message: 正文 - /// - Parameter icon: 图标 - @discardableResult func push(alert scene: Alert.Scene, title: String? = nil, message: String? = nil, actions: ((Alert) -> Void)? = nil) -> Alert { - let a = Alert(scene: scene, title: title, message: message) - actions?(a) - a.view.layoutIfNeeded() - return push(a) + /// - Parameter actions: 更多操作 + @discardableResult class func push(alert scene: Alert.Scene, title: String? = nil, message: String? = nil, actions: ((Alert) -> Void)? = nil) -> Alert { + return Alert(scene: scene, title: title, message: message, actions: actions).push() } /// 获取指定的实例 /// - Parameter identifier: 指定实例的标识 - func alert(_ identifier: String?) -> Alert? { + class func alerts(_ identifier: String?) -> [Alert] { var aa = [Alert]() - for a in alerts { + for a in Alert.alerts { if a.identifier == identifier { aa.append(a) } } - return aa.last - } - - /// 弹出屏幕 - /// - Parameter alert: 实例 - func pop(_ alert: Alert) { - for a in alerts { - if a == alert { - a.pop() - } - } - } - - /// 弹出实例 - /// - Parameter identifier: 指定实例的标识 - func pop(alert identifier: String?) { - for a in alerts { - if a.identifier == identifier { - a.pop() - } - } - } - -} - - -// MARK: 类函数 - -public extension ProHUD { - - /// 推入屏幕 - /// - Parameter alert: 实例 - @discardableResult class func push(_ alert: Alert) -> Alert { - return shared.push(alert) - } - - /// 推入屏幕 - /// - Parameter alert: 场景 - /// - Parameter title: 标题 - /// - Parameter message: 正文 - /// - Parameter icon: 图标 - @discardableResult class func push(alert: Alert.Scene, title: String? = nil, message: String? = nil, actions: ((Alert) -> Void)? = nil) -> Alert { - return shared.push(alert: alert, title: title, message: message, actions: actions) - } - - /// 获取指定的实例 - /// - Parameter identifier: 指定实例的标识 - class func alert(_ identifier: String?) -> Alert? { - return shared.alert(identifier) + return aa } /// 弹出屏幕 /// - Parameter alert: 实例 class func pop(_ alert: Alert) { - shared.pop(alert) + alert.pop() } - /// 弹出实例 + /// 弹出屏幕 /// - Parameter identifier: 指定实例的标识 - class func pop(alert identifier: String?) { - shared.pop(alert: identifier) + class func pop(_ identifier: String?) { + for a in alerts(identifier) { + a.pop() + } } } // MARK: - 私有 -fileprivate extension ProHUD.Alert { +fileprivate extension Alert { /// 移除按钮 /// - Parameter index: 索引 - @discardableResult func privRemoveAction(index: Int) -> ProHUD.Alert { + @discardableResult func privRemoveAction(index: Int) -> Alert { if index < 0 { for view in self.actionStack.arrangedSubviews { if let btn = view as? UIButton { @@ -401,9 +331,8 @@ fileprivate extension ProHUD.Alert { } -internal extension ProHUD { - - func updateAlertsLayout() { +fileprivate extension Alert { + class func updateAlertsLayout() { for (i, a) in alerts.reversed().enumerated() { let scale = CGFloat(pow(0.7, CGFloat(i))) UIView.animate(withDuration: 1.8, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0.5, options: [.allowUserInteraction, .curveEaseInOut], animations: { @@ -414,11 +343,7 @@ internal extension ProHUD { } } } -} - -fileprivate extension ProHUD { - - func getAlertWindow(_ vc: UIViewController) -> UIWindow { + class func getAlertWindow(_ vc: UIViewController) -> UIWindow { if let w = alertWindow { return w } @@ -430,7 +355,7 @@ fileprivate extension ProHUD { return w } - func removeItemFromArray(alert: Alert) { + class func removeItemFromArray(alert: Alert) { if alerts.count > 1 { for (i, a) in alerts.enumerated() { if a == alert { diff --git a/ProHUD/Alert/AlertModel.swift b/ProHUD/Alert/AlertModel.swift index 2468b96..ca210b0 100644 --- a/ProHUD/Alert/AlertModel.swift +++ b/ProHUD/Alert/AlertModel.swift @@ -8,7 +8,7 @@ import UIKit -public extension ProHUD.Alert { +public extension Alert { enum Scene { /// 默认场景 case `default` diff --git a/ProHUD/Alert/AlertView.swift b/ProHUD/Alert/AlertView.swift index 683e82b..a384214 100644 --- a/ProHUD/Alert/AlertView.swift +++ b/ProHUD/Alert/AlertView.swift @@ -8,7 +8,7 @@ import UIKit -internal extension ProHUD.Alert { +internal extension Alert { class Button: UIButton { class func actionButton(title: String?) -> UIButton { let btn = Button(type: .system) diff --git a/ProHUD/Guard/GuardController.swift b/ProHUD/Guard/GuardController.swift index 56451d5..485fc96 100644 --- a/ProHUD/Guard/GuardController.swift +++ b/ProHUD/Guard/GuardController.swift @@ -91,7 +91,7 @@ public extension Guard { /// 推入某个视图控制器 /// - Parameter viewController: 视图控制器 - func push(to viewController: UIViewController? = nil) { + func push(to viewController: UIViewController? = nil) -> Guard { func f(_ vc: UIViewController) { view.layoutIfNeeded() vc.addChild(self) @@ -113,25 +113,19 @@ public extension Guard { } else { debug("请传入需要push到的控制器") } + return self } /// 从父视图控制器弹出 - func pop(animated: Bool = true) { + func pop() { if displaying { debug("pop") displaying = false view.isUserInteractionEnabled = false self.removeFromParent() - if animated { - UIView.animateForGuard(animations: { - self.translateOut() - }) { (done) in - if self.displaying == false { - self.view.removeFromSuperview() - } - } - } else { + UIView.animateForGuard(animations: { self.translateOut() + }) { (done) in if self.displaying == false { self.view.removeFromSuperview() } @@ -139,6 +133,8 @@ public extension Guard { } } + // MARK: 设置函数 + /// 加载一个标题 /// - Parameter text: 文本 @discardableResult func add(title: String?) -> UILabel { @@ -231,20 +227,24 @@ public extension Guard { /// - Parameter message: 正文 /// - Parameter icon: 图标 @discardableResult class func push(to viewController: UIViewController? = nil, actions: ((Guard) -> Void)? = nil) -> Guard { - let g = Guard(actions: actions) - g.push(to: viewController) - return g + return Guard(actions: actions).push(to: viewController) } /// 获取指定的实例 /// - Parameter identifier: 指定实例的标识 - class func guards(_ identifier: String?, from viewController: UIViewController? = nil) -> [Guard] { + class func guards(_ identifier: String? = nil, from viewController: UIViewController? = nil) -> [Guard] { var gg = [Guard]() if let vc = viewController ?? cfg.rootViewController { for child in vc.children { if child.isKind(of: Guard.self) { if let g = child as? Guard { - gg.append(g) + if let id = identifier { + if g.identifier == id { + gg.append(g) + } + } else { + gg.append(g) + } } } } @@ -258,6 +258,13 @@ public extension Guard { `guard`.pop() } + /// 弹出屏幕 + /// - Parameter identifier: 指定实例的标识 + class func pop(from viewController: UIViewController?) { + for g in guards(from: viewController) { + g.pop() + } + } } diff --git a/ProHUD/Guard/GuardView.swift b/ProHUD/Guard/GuardView.swift index 98a3cf2..5d335ec 100644 --- a/ProHUD/Guard/GuardView.swift +++ b/ProHUD/Guard/GuardView.swift @@ -8,7 +8,7 @@ import UIKit -internal extension ProHUD.Guard { +internal extension Guard { class Button: UIButton { class func actionButton(title: String?) -> Button { diff --git a/ProHUD/ProHUD.swift b/ProHUD/ProHUD.swift index 1cca6d4..0a0b605 100644 --- a/ProHUD/ProHUD.swift +++ b/ProHUD/ProHUD.swift @@ -16,12 +16,6 @@ public class ProHUD { return cfg } - internal var toasts = [Toast]() - internal var alerts = [Alert]() - - internal var alertWindow: UIWindow? - - } // MARK: - Utilities @@ -30,7 +24,7 @@ internal extension ProHUD { /// 获取Bundle static var bundle: Bundle { - var b = Bundle.init(for: ProHUD.Alert.self) + var b = Bundle.init(for: Alert.self) let p = b.path(forResource: "ProHUD", ofType: "bundle") if let bb = Bundle.init(path: p ?? "") { b = bb diff --git a/ProHUD/Toast/ToastController.swift b/ProHUD/Toast/ToastController.swift index 546d20a..dadcbee 100644 --- a/ProHUD/Toast/ToastController.swift +++ b/ProHUD/Toast/ToastController.swift @@ -9,9 +9,13 @@ import UIKit import Inspire +public typealias Toast = ProHUD.Toast + public extension ProHUD { class Toast: HUDController { + internal static var toasts = [Toast]() + public var window: UIWindow? /// 图标 @@ -68,14 +72,14 @@ public extension ProHUD { /// - Parameter title: 标题 /// - Parameter message: 内容 /// - Parameter icon: 图标 - public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil) { + public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil, actions: ((Toast) -> Void)? = nil) { self.init() model.scene = scene model.title = title model.message = message model.icon = icon - + actions?(self) // 布局 cfg.toast.loadSubviews(self) cfg.toast.reloadData(self) @@ -96,18 +100,66 @@ public extension ProHUD { // MARK: - 实例函数 -public extension ProHUD.Toast { +public extension Toast { // MARK: 生命周期函数 /// 推入屏幕 - func push() { - ProHUD.push(self) + @discardableResult func push() -> Toast { + let config = cfg.toast + let isNew: Bool + if self.window == nil { + let w = UIWindow(frame: .zero) + self.window = w + w.windowLevel = UIWindow.Level(5000) + w.backgroundColor = .clear + w.layer.shadowRadius = 8 + w.layer.shadowOffset = .init(width: 0, height: 5) + w.layer.shadowOpacity = 0.2 + w.isHidden = false + isNew = true + } else { + isNew = false + } + + let window = self.window! + // background & frame + // 设定正确的宽度,更新子视图 + let width = CGFloat.minimum(UIScreen.main.bounds.width - 2*config.margin, config.maxWidth) + view.frame.size = CGSize(width: width, height: 800) + titleLabel.sizeToFit() + bodyLabel.sizeToFit() + view.layoutIfNeeded() + // 更新子视图之后获取正确的高度 + var height = CGFloat(0) + for v in self.view.subviews { + height = CGFloat.maximum(v.frame.maxY, height) + } + height += config.padding + // 应用到frame + window.frame = CGRect(x: (UIScreen.main.bounds.width - width) / 2, y: 0, width: width, height: height) + backgroundView.frame.size = window.frame.size + window.insertSubview(backgroundView, at: 0) + window.rootViewController = self // 此时toast.view.frame.size会自动更新为window.frame.size + // 根据在屏幕中的顺序,确定y坐标 + if Toast.toasts.contains(self) == false { + Toast.toasts.append(self) + } + Toast.updateToastsLayout() + if isNew { + window.transform = .init(translationX: 0, y: -window.frame.maxY) + UIView.animateForToast { + window.transform = .identity + } + } else { + view.layoutIfNeeded() + } + return self } /// 弹出屏幕 func pop() { - ProHUD.shared.removeItemFromArray(toast: self) + Toast.removeItemFromArray(toast: self) UIView.animateForToast(animations: { let frame = self.window?.frame ?? .zero self.window?.transform = .init(translationX: 0, y: -200-frame.maxY) @@ -122,7 +174,7 @@ public extension ProHUD.Toast { /// 设置持续时间 /// - Parameter duration: 持续时间 - @discardableResult func duration(_ duration: TimeInterval?) -> ProHUD.Toast { + @discardableResult func duration(_ duration: TimeInterval?) -> Toast { model.setupDuration(duration: duration) { [weak self] in self?.pop() } @@ -131,14 +183,14 @@ public extension ProHUD.Toast { /// 点击事件 /// - Parameter callback: 事件回调 - @discardableResult func didTapped(_ callback: (() -> Void)?) -> ProHUD.Toast { + @discardableResult func didTapped(_ callback: (() -> Void)?) -> Toast { model.tapCallback = callback return self } /// 消失事件 /// - Parameter callback: 事件回调 - @discardableResult func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Toast { + @discardableResult func didDisappear(_ callback: (() -> Void)?) -> Toast { disappearCallback = callback return self } @@ -147,7 +199,7 @@ public extension ProHUD.Toast { /// - Parameter scene: 场景 /// - Parameter title: 标题 /// - Parameter message: 内容 - @discardableResult func update(scene: Scene, title: String?, message: String?) -> ProHUD.Toast { + @discardableResult func update(scene: Scene, title: String?, message: String?) -> Toast { model.scene = scene model.title = title model.message = message @@ -157,7 +209,7 @@ public extension ProHUD.Toast { /// 更新标题 /// - Parameter title: 标题 - @discardableResult func update(title: String?) -> ProHUD.Toast { + @discardableResult func update(title: String?) -> Toast { model.title = title cfg.toast.reloadData(self) return self @@ -165,7 +217,7 @@ public extension ProHUD.Toast { /// 更新文本 /// - Parameter message: 消息 - @discardableResult func update(message: String?) -> ProHUD.Toast { + @discardableResult func update(message: String?) -> Toast { model.message = message cfg.toast.reloadData(self) return self @@ -173,7 +225,7 @@ public extension ProHUD.Toast { /// 更新图标 /// - Parameter icon: 图标 - @discardableResult func update(icon: UIImage?) -> ProHUD.Toast { + @discardableResult func update(icon: UIImage?) -> Toast { model.icon = icon cfg.toast.reloadData(self) return self @@ -181,7 +233,53 @@ public extension ProHUD.Toast { } -fileprivate extension ProHUD.Toast { + +// MARK: 类函数 + +public extension Toast { + + /// 推入屏幕 + /// - Parameter toast: 场景 + /// - Parameter title: 标题 + /// - Parameter message: 内容 + /// - Parameter actions: 更多操作 + @discardableResult class func push(toast scene: Toast.Scene, title: String? = nil, message: String? = nil, actions: ((Toast) -> Void)? = nil) -> Toast { + return Toast(scene: scene, title: title, message: message, actions: actions).push() + } + + /// 获取指定的toast + /// - Parameter identifier: 标识 + class func toasts(_ identifier: String?) -> [Toast] { + var tt = [Toast]() + for t in toasts { + if t.identifier == identifier { + tt.append(t) + } + } + return tt + } + + /// 弹出屏幕 + /// - Parameter toast: 实例 + class func pop(_ toast: Toast) { + toast.pop() + } + + /// 弹出屏幕 + /// - Parameter identifier: 指定实例的标识 + class func pop(_ identifier: String?) { + for t in toasts(identifier) { + t.pop() + } + } + +} + +// MARK: 私有 + +fileprivate var willUpdateToastsLayout: DispatchWorkItem? + +fileprivate extension Toast { /// 点击事件 /// - Parameter sender: 手势 @@ -210,159 +308,24 @@ fileprivate extension ProHUD.Toast { } } } -} - - -// MARK: - 实例函数 - -public extension ProHUD { - /// Toast推入屏幕 + /// 从数组中移除 /// - Parameter toast: 实例 - @discardableResult func push(_ toast: Toast) -> Toast { - let config = cfg.toast - let isNew: Bool - if toast.window == nil { - let w = UIWindow(frame: .zero) - toast.window = w - w.windowLevel = UIWindow.Level(5000) - w.backgroundColor = .clear - w.layer.shadowRadius = 8 - w.layer.shadowOffset = .init(width: 0, height: 5) - w.layer.shadowOpacity = 0.2 - w.isHidden = false - isNew = true + class func removeItemFromArray(toast: Toast) { + if toasts.count > 1 { + for (i, t) in toasts.enumerated() { + if t == toast { + toasts.remove(at: i) + } + } + updateToastsLayout() + } else if toasts.count == 1 { + toasts.removeAll() } else { - isNew = false - } - - let window = toast.window! - // background & frame - // 设定正确的宽度,更新子视图 - let width = CGFloat.minimum(UIScreen.main.bounds.width - 2*config.margin, config.maxWidth) - toast.view.frame.size = CGSize(width: width, height: 800) - toast.titleLabel.sizeToFit() - toast.bodyLabel.sizeToFit() - toast.view.layoutIfNeeded() - // 更新子视图之后获取正确的高度 - var height = CGFloat(0) - for v in toast.view.subviews { - height = CGFloat.maximum(v.frame.maxY, height) - } - height += config.padding - // 应用到frame - window.frame = CGRect(x: (UIScreen.main.bounds.width - width) / 2, y: 0, width: width, height: height) - toast.backgroundView.frame.size = window.frame.size - window.insertSubview(toast.backgroundView, at: 0) - window.rootViewController = toast // 此时toast.view.frame.size会自动更新为window.frame.size - // 根据在屏幕中的顺序,确定y坐标 - if toasts.contains(toast) == false { - toasts.append(toast) - } - updateToastsLayout() - if isNew { - window.transform = .init(translationX: 0, y: -window.frame.maxY) - UIView.animateForToast { - window.transform = .identity - } - } else { - toast.view.layoutIfNeeded() - } - return toast - } - - /// Toast推入屏幕 - /// - Parameter toast: 场景 - /// - Parameter title: 标题 - /// - Parameter message: 内容 - /// - Parameter icon: 图标 - @discardableResult func push(toast scene: Toast.Scene, title: String? = nil, message: String? = nil, actions: ((Toast) -> Void)? = nil) -> Toast { - let t = Toast(scene: scene, title: title, message: message) - actions?(t) - t.view.layoutIfNeeded() - return push(t) - } - - /// 获取指定的toast - /// - Parameter identifier: 标识 - func toast(_ identifier: String?) -> Toast? { - var tt = [Toast]() - for t in toasts { - if t.identifier == identifier { - tt.append(t) - } - } - return tt.last - } - - /// Toast弹出屏幕 - /// - Parameter toast: 实例 - func pop(_ toast: Toast) { - for t in toasts { - if t == toast { - t.pop() - } + debug("漏洞:已经没有toast了") } } - - /// Toast弹出屏幕 - /// - Parameter identifier: 需要弹出的Toast的标识 - func pop(toast identifier: String?) { - for t in toasts { - if t.identifier == identifier { - t.pop() - } - } - } - -} - - -// MARK: 类函数 - -public extension ProHUD { - - /// Toast推入屏幕 - /// - Parameter toast: 实例 - @discardableResult class func push(_ toast: Toast) -> Toast { - return shared.push(toast) - } - - /// Toast推入屏幕 - /// - Parameter toast: 场景 - /// - Parameter title: 标题 - /// - Parameter message: 内容 - /// - Parameter icon: 图标 - @discardableResult class func push(toast: Toast.Scene, title: String? = nil, message: String? = nil, actions: ((Toast) -> Void)? = nil) -> Toast { - return shared.push(toast: toast, title: title, message: message, actions: actions) - } - - /// 获取指定的toast - /// - Parameter identifier: 标识 - class func toast(_ identifier: String?) -> Toast? { - return shared.toast(identifier) - } - - /// Toast弹出屏幕 - /// - Parameter toast: 实例 - class func pop(_ toast: Toast) { - shared.pop(toast) - } - - /// Toast弹出屏幕 - /// - Parameter identifier: 需要弹出的Toast的标识 - class func pop(toast identifier: String?) { - shared.pop(toast: identifier) - } - -} - -// MARK: 私有 - -fileprivate var willUpdateToastsLayout: DispatchWorkItem? - -internal extension ProHUD { - func updateToastsLayout() { + class func updateToastsLayout() { func f() { let top = Inspire.shared.screen.updatedSafeAreaInsets.top for (i, e) in toasts.enumerated() { @@ -391,28 +354,6 @@ internal extension ProHUD { }) DispatchQueue.main.asyncAfter(deadline: .now()+0.001, execute: willUpdateToastsLayout!) } - -} - -internal extension ProHUD { - - /// 从数组中移除 - /// - Parameter toast: 实例 - func removeItemFromArray(toast: Toast) { - if toasts.count > 1 { - for (i, t) in toasts.enumerated() { - if t == toast { - toasts.remove(at: i) - } - } - updateToastsLayout() - } else if toasts.count == 1 { - toasts.removeAll() - } else { - debug("漏洞:已经没有toast了") - } - } - } diff --git a/ProHUD/Toast/ToastModel.swift b/ProHUD/Toast/ToastModel.swift index 6fe3c76..2cafc4a 100644 --- a/ProHUD/Toast/ToastModel.swift +++ b/ProHUD/Toast/ToastModel.swift @@ -8,7 +8,7 @@ import UIKit -public extension ProHUD.Toast { +public extension Toast { enum Scene { /// 默认场景 case `default`