This commit is contained in:
xaoxuu 2019-08-08 11:09:22 +08:00
parent c165d05de4
commit 4cebb3fc72
8 changed files with 224 additions and 357 deletions

View File

@ -9,9 +9,15 @@
import UIKit import UIKit
import SnapKit import SnapKit
public typealias Alert = ProHUD.Alert
public extension ProHUD { public extension ProHUD {
class Alert: HUDController { class Alert: HUDController {
internal static var alerts = [Alert]()
internal static var alertWindow: UIWindow?
/// ///
public var contentView = BlurView() public var contentView = BlurView()
@ -57,14 +63,14 @@ public extension ProHUD {
/// - Parameter title: /// - Parameter title:
/// - Parameter message: /// - Parameter message:
/// - Parameter icon: /// - 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() self.init()
view.tintColor = cfg.alert.tintColor view.tintColor = cfg.alert.tintColor
model.scene = scene model.scene = scene
model.title = title model.title = title
model.message = message model.message = message
model.icon = icon model.icon = icon
actions?(self)
willLayoutSubviews() willLayoutSubviews()
} }
@ -76,20 +82,40 @@ public extension ProHUD {
// MARK: - // MARK: -
public extension ProHUD.Alert { public extension Alert {
// MARK: // MARK:
/// ///
@discardableResult func push() -> ProHUD.Alert { @discardableResult func push() -> Alert {
return ProHUD.push(self) 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() { func pop() {
let hud = ProHUD.shared let window = Alert.getAlertWindow(self)
let window = hud.getAlertWindow(self) Alert.removeItemFromArray(alert: self)
hud.removeItemFromArray(alert: self)
UIView.animateForAlertBuildOut(animations: { UIView.animateForAlertBuildOut(animations: {
self.view.alpha = 0 self.view.alpha = 0
self.view.transform = .init(scaleX: 1.08, y: 1.08) self.view.transform = .init(scaleX: 1.08, y: 1.08)
@ -98,12 +124,12 @@ public extension ProHUD.Alert {
self.removeFromParent() self.removeFromParent()
} }
// hide window // hide window
let count = hud.alerts.count let count = Alert.alerts.count
if count == 0 && hud.alertWindow != nil { if count == 0 && Alert.alertWindow != nil {
UIView.animateForAlertBuildOut(animations: { UIView.animateForAlertBuildOut(animations: {
window.backgroundColor = window.backgroundColor?.withAlphaComponent(0) window.backgroundColor = window.backgroundColor?.withAlphaComponent(0)
}) { (done) in }) { (done) in
hud.alertWindow = nil Alert.alertWindow = nil
} }
} }
} }
@ -114,39 +140,32 @@ public extension ProHUD.Alert {
/// ///
/// - Parameter style: /// - Parameter style:
/// - Parameter text: /// - Parameter text:
/// - Parameter action: /// - Parameter handler:
@discardableResult func add(action style: UIAlertAction.Style, title: String?, handler: (() -> Void)?) -> ProHUD.Alert { @discardableResult func add(action style: UIAlertAction.Style, title: String?, handler: (() -> Void)?) -> UIButton {
if let btn = privAddButton(custom: Button.actionButton(title: title), action: handler) as? Button { let btn = privAddButton(custom: Button.actionButton(title: title), action: handler)
btn.update(style: style) if let b = btn as? Button {
b.update(style: style)
} }
return self return btn
}
///
/// - Parameter button:
/// - Parameter action:
@discardableResult func add(button: UIButton, action: (() -> Void)?) -> ProHUD.Alert {
privAddButton(custom: button, action: action)
return self
} }
/// ///
/// - Parameter callback: /// - Parameter callback:
@discardableResult func didForceQuit(_ callback: (() -> Void)?) -> ProHUD.Alert { @discardableResult func didForceQuit(_ callback: (() -> Void)?) -> Alert {
model.forceQuitCallback = callback model.forceQuitCallback = callback
return self return self
} }
/// ///
/// - Parameter callback: /// - Parameter callback:
@discardableResult func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Alert { @discardableResult func didDisappear(_ callback: (() -> Void)?) -> Alert {
disappearCallback = callback disappearCallback = callback
return self return self
} }
/// ///
/// - Parameter duration: /// - Parameter duration:
@discardableResult func duration(_ duration: TimeInterval?) -> ProHUD.Alert { @discardableResult func duration(_ duration: TimeInterval?) -> Alert {
model.setupDuration(duration: duration) { [weak self] in model.setupDuration(duration: duration) { [weak self] in
self?.pop() self?.pop()
} }
@ -157,7 +176,7 @@ public extension ProHUD.Alert {
/// - Parameter scene: /// - Parameter scene:
/// - Parameter title: /// - Parameter title:
/// - Parameter message: /// - 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.scene = scene
model.title = title model.title = title
model.message = message model.message = message
@ -167,7 +186,7 @@ public extension ProHUD.Alert {
/// ///
/// - Parameter icon: /// - Parameter icon:
@discardableResult func update(icon: UIImage?) -> ProHUD.Alert { @discardableResult func update(icon: UIImage?) -> Alert {
model.icon = icon model.icon = icon
cfg.alert.reloadData(self) cfg.alert.reloadData(self)
imageView?.layer.removeAllAnimations() imageView?.layer.removeAllAnimations()
@ -179,36 +198,23 @@ public extension ProHUD.Alert {
/// - Parameter style: /// - Parameter style:
/// - Parameter title: /// - Parameter title:
/// - Parameter action: /// - Parameter action:
@discardableResult func update(action index: Int, style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> ProHUD.Alert { @discardableResult func update(action index: Int, style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> Alert {
return update(action: index, button: { (btn) in if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton {
btn.setTitle(title, for: .normal) btn.setTitle(title, for: .normal)
if let b = btn as? Button { if let b = btn as? Button {
b.update(style: style) b.update(style: style)
} }
btn.layoutIfNeeded() 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 { if let ac = action {
addTouchUpAction(for: btn, action: ac) addTouchUpAction(for: btn, action: ac)
} }
} }
UIView.animateForAlert {
self.view.layoutIfNeeded()
}
return self return self
} }
/// ///
/// - Parameter index: /// - Parameter index:
@discardableResult func remove(action index: Int...) -> ProHUD.Alert { @discardableResult func remove(action index: Int...) -> Alert {
for (i, idx) in index.enumerated() { for (i, idx) in index.enumerated() {
privRemoveAction(index: idx-i) privRemoveAction(index: idx-i)
} }
@ -218,130 +224,54 @@ public extension ProHUD.Alert {
} }
// MARK:
// MARK: - public extension Alert {
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
}
/// ///
/// - Parameter alert: /// - Parameter alert:
/// - Parameter title: /// - Parameter title:
/// - Parameter message: /// - Parameter message:
/// - Parameter icon: /// - Parameter actions:
@discardableResult func push(alert scene: Alert.Scene, title: String? = nil, message: String? = nil, actions: ((Alert) -> Void)? = nil) -> Alert { @discardableResult class 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) return Alert(scene: scene, title: title, message: message, actions: actions).push()
actions?(a)
a.view.layoutIfNeeded()
return push(a)
} }
/// ///
/// - Parameter identifier: /// - Parameter identifier:
func alert(_ identifier: String?) -> Alert? { class func alerts(_ identifier: String?) -> [Alert] {
var aa = [Alert]() var aa = [Alert]()
for a in alerts { for a in Alert.alerts {
if a.identifier == identifier { if a.identifier == identifier {
aa.append(a) aa.append(a)
} }
} }
return aa.last return aa
}
///
/// - 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)
} }
/// ///
/// - Parameter alert: /// - Parameter alert:
class func pop(_ alert: Alert) { class func pop(_ alert: Alert) {
shared.pop(alert) alert.pop()
} }
/// ///
/// - Parameter identifier: /// - Parameter identifier:
class func pop(alert identifier: String?) { class func pop(_ identifier: String?) {
shared.pop(alert: identifier) for a in alerts(identifier) {
a.pop()
}
} }
} }
// MARK: - // MARK: -
fileprivate extension ProHUD.Alert { fileprivate extension Alert {
/// ///
/// - Parameter index: /// - Parameter index:
@discardableResult func privRemoveAction(index: Int) -> ProHUD.Alert { @discardableResult func privRemoveAction(index: Int) -> Alert {
if index < 0 { if index < 0 {
for view in self.actionStack.arrangedSubviews { for view in self.actionStack.arrangedSubviews {
if let btn = view as? UIButton { if let btn = view as? UIButton {
@ -401,9 +331,8 @@ fileprivate extension ProHUD.Alert {
} }
internal extension ProHUD { fileprivate extension Alert {
class func updateAlertsLayout() {
func updateAlertsLayout() {
for (i, a) in alerts.reversed().enumerated() { for (i, a) in alerts.reversed().enumerated() {
let scale = CGFloat(pow(0.7, CGFloat(i))) let scale = CGFloat(pow(0.7, CGFloat(i)))
UIView.animate(withDuration: 1.8, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0.5, options: [.allowUserInteraction, .curveEaseInOut], animations: { UIView.animate(withDuration: 1.8, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0.5, options: [.allowUserInteraction, .curveEaseInOut], animations: {
@ -414,11 +343,7 @@ internal extension ProHUD {
} }
} }
} }
} class func getAlertWindow(_ vc: UIViewController) -> UIWindow {
fileprivate extension ProHUD {
func getAlertWindow(_ vc: UIViewController) -> UIWindow {
if let w = alertWindow { if let w = alertWindow {
return w return w
} }
@ -430,7 +355,7 @@ fileprivate extension ProHUD {
return w return w
} }
func removeItemFromArray(alert: Alert) { class func removeItemFromArray(alert: Alert) {
if alerts.count > 1 { if alerts.count > 1 {
for (i, a) in alerts.enumerated() { for (i, a) in alerts.enumerated() {
if a == alert { if a == alert {

View File

@ -8,7 +8,7 @@
import UIKit import UIKit
public extension ProHUD.Alert { public extension Alert {
enum Scene { enum Scene {
/// ///
case `default` case `default`

View File

@ -8,7 +8,7 @@
import UIKit import UIKit
internal extension ProHUD.Alert { internal extension Alert {
class Button: UIButton { class Button: UIButton {
class func actionButton(title: String?) -> UIButton { class func actionButton(title: String?) -> UIButton {
let btn = Button(type: .system) let btn = Button(type: .system)

View File

@ -91,7 +91,7 @@ public extension Guard {
/// ///
/// - Parameter viewController: /// - Parameter viewController:
func push(to viewController: UIViewController? = nil) { func push(to viewController: UIViewController? = nil) -> Guard {
func f(_ vc: UIViewController) { func f(_ vc: UIViewController) {
view.layoutIfNeeded() view.layoutIfNeeded()
vc.addChild(self) vc.addChild(self)
@ -113,16 +113,16 @@ public extension Guard {
} else { } else {
debug("请传入需要push到的控制器") debug("请传入需要push到的控制器")
} }
return self
} }
/// ///
func pop(animated: Bool = true) { func pop() {
if displaying { if displaying {
debug("pop") debug("pop")
displaying = false displaying = false
view.isUserInteractionEnabled = false view.isUserInteractionEnabled = false
self.removeFromParent() self.removeFromParent()
if animated {
UIView.animateForGuard(animations: { UIView.animateForGuard(animations: {
self.translateOut() self.translateOut()
}) { (done) in }) { (done) in
@ -130,15 +130,11 @@ public extension Guard {
self.view.removeFromSuperview() self.view.removeFromSuperview()
} }
} }
} else {
self.translateOut()
if self.displaying == false {
self.view.removeFromSuperview()
}
}
} }
} }
// MARK:
/// ///
/// - Parameter text: /// - Parameter text:
@discardableResult func add(title: String?) -> UILabel { @discardableResult func add(title: String?) -> UILabel {
@ -231,21 +227,25 @@ public extension Guard {
/// - Parameter message: /// - Parameter message:
/// - Parameter icon: /// - Parameter icon:
@discardableResult class func push(to viewController: UIViewController? = nil, actions: ((Guard) -> Void)? = nil) -> Guard { @discardableResult class func push(to viewController: UIViewController? = nil, actions: ((Guard) -> Void)? = nil) -> Guard {
let g = Guard(actions: actions) return Guard(actions: actions).push(to: viewController)
g.push(to: viewController)
return g
} }
/// ///
/// - Parameter identifier: /// - 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]() var gg = [Guard]()
if let vc = viewController ?? cfg.rootViewController { if let vc = viewController ?? cfg.rootViewController {
for child in vc.children { for child in vc.children {
if child.isKind(of: Guard.self) { if child.isKind(of: Guard.self) {
if let g = child as? Guard { if let g = child as? Guard {
if let id = identifier {
if g.identifier == id {
gg.append(g) gg.append(g)
} }
} else {
gg.append(g)
}
}
} }
} }
} }
@ -258,6 +258,13 @@ public extension Guard {
`guard`.pop() `guard`.pop()
} }
///
/// - Parameter identifier:
class func pop(from viewController: UIViewController?) {
for g in guards(from: viewController) {
g.pop()
}
}
} }

View File

@ -8,7 +8,7 @@
import UIKit import UIKit
internal extension ProHUD.Guard { internal extension Guard {
class Button: UIButton { class Button: UIButton {
class func actionButton(title: String?) -> Button { class func actionButton(title: String?) -> Button {

View File

@ -16,12 +16,6 @@ public class ProHUD {
return cfg return cfg
} }
internal var toasts = [Toast]()
internal var alerts = [Alert]()
internal var alertWindow: UIWindow?
} }
// MARK: - Utilities // MARK: - Utilities
@ -30,7 +24,7 @@ internal extension ProHUD {
/// Bundle /// Bundle
static var bundle: 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") let p = b.path(forResource: "ProHUD", ofType: "bundle")
if let bb = Bundle.init(path: p ?? "") { if let bb = Bundle.init(path: p ?? "") {
b = bb b = bb

View File

@ -9,9 +9,13 @@
import UIKit import UIKit
import Inspire import Inspire
public typealias Toast = ProHUD.Toast
public extension ProHUD { public extension ProHUD {
class Toast: HUDController { class Toast: HUDController {
internal static var toasts = [Toast]()
public var window: UIWindow? public var window: UIWindow?
/// ///
@ -68,14 +72,14 @@ public extension ProHUD {
/// - Parameter title: /// - Parameter title:
/// - Parameter message: /// - Parameter message:
/// - Parameter icon: /// - 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() self.init()
model.scene = scene model.scene = scene
model.title = title model.title = title
model.message = message model.message = message
model.icon = icon model.icon = icon
actions?(self)
// //
cfg.toast.loadSubviews(self) cfg.toast.loadSubviews(self)
cfg.toast.reloadData(self) cfg.toast.reloadData(self)
@ -96,18 +100,66 @@ public extension ProHUD {
// MARK: - // MARK: -
public extension ProHUD.Toast { public extension Toast {
// MARK: // MARK:
/// ///
func push() { @discardableResult func push() -> Toast {
ProHUD.push(self) 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.sizewindow.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() { func pop() {
ProHUD.shared.removeItemFromArray(toast: self) Toast.removeItemFromArray(toast: self)
UIView.animateForToast(animations: { UIView.animateForToast(animations: {
let frame = self.window?.frame ?? .zero let frame = self.window?.frame ?? .zero
self.window?.transform = .init(translationX: 0, y: -200-frame.maxY) self.window?.transform = .init(translationX: 0, y: -200-frame.maxY)
@ -122,7 +174,7 @@ public extension ProHUD.Toast {
/// ///
/// - Parameter duration: /// - Parameter duration:
@discardableResult func duration(_ duration: TimeInterval?) -> ProHUD.Toast { @discardableResult func duration(_ duration: TimeInterval?) -> Toast {
model.setupDuration(duration: duration) { [weak self] in model.setupDuration(duration: duration) { [weak self] in
self?.pop() self?.pop()
} }
@ -131,14 +183,14 @@ public extension ProHUD.Toast {
/// ///
/// - Parameter callback: /// - Parameter callback:
@discardableResult func didTapped(_ callback: (() -> Void)?) -> ProHUD.Toast { @discardableResult func didTapped(_ callback: (() -> Void)?) -> Toast {
model.tapCallback = callback model.tapCallback = callback
return self return self
} }
/// ///
/// - Parameter callback: /// - Parameter callback:
@discardableResult func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Toast { @discardableResult func didDisappear(_ callback: (() -> Void)?) -> Toast {
disappearCallback = callback disappearCallback = callback
return self return self
} }
@ -147,7 +199,7 @@ public extension ProHUD.Toast {
/// - Parameter scene: /// - Parameter scene:
/// - Parameter title: /// - Parameter title:
/// - Parameter message: /// - 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.scene = scene
model.title = title model.title = title
model.message = message model.message = message
@ -157,7 +209,7 @@ public extension ProHUD.Toast {
/// ///
/// - Parameter title: /// - Parameter title:
@discardableResult func update(title: String?) -> ProHUD.Toast { @discardableResult func update(title: String?) -> Toast {
model.title = title model.title = title
cfg.toast.reloadData(self) cfg.toast.reloadData(self)
return self return self
@ -165,7 +217,7 @@ public extension ProHUD.Toast {
/// ///
/// - Parameter message: /// - Parameter message:
@discardableResult func update(message: String?) -> ProHUD.Toast { @discardableResult func update(message: String?) -> Toast {
model.message = message model.message = message
cfg.toast.reloadData(self) cfg.toast.reloadData(self)
return self return self
@ -173,7 +225,7 @@ public extension ProHUD.Toast {
/// ///
/// - Parameter icon: /// - Parameter icon:
@discardableResult func update(icon: UIImage?) -> ProHUD.Toast { @discardableResult func update(icon: UIImage?) -> Toast {
model.icon = icon model.icon = icon
cfg.toast.reloadData(self) cfg.toast.reloadData(self)
return 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: /// - Parameter sender:
@ -210,159 +308,24 @@ fileprivate extension ProHUD.Toast {
} }
} }
} }
}
///
// MARK: -
public extension ProHUD {
/// Toast
/// - Parameter toast: /// - Parameter toast:
@discardableResult func push(_ toast: Toast) -> Toast { class func removeItemFromArray(toast: Toast) {
let config = cfg.toast if toasts.count > 1 {
let isNew: Bool for (i, t) in toasts.enumerated() {
if toast.window == nil { if t == toast {
let w = UIWindow(frame: .zero) toasts.remove(at: i)
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
} 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.sizewindow.frame.size
// y
if toasts.contains(toast) == false {
toasts.append(toast)
} }
updateToastsLayout() updateToastsLayout()
if isNew { } else if toasts.count == 1 {
window.transform = .init(translationX: 0, y: -window.frame.maxY) toasts.removeAll()
UIView.animateForToast {
window.transform = .identity
}
} else { } else {
toast.view.layoutIfNeeded() debug("漏洞已经没有toast了")
}
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 class func updateToastsLayout() {
}
/// Toast
/// - Parameter toast:
func pop(_ toast: Toast) {
for t in toasts {
if t == toast {
t.pop()
}
}
}
/// 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() {
func f() { func f() {
let top = Inspire.shared.screen.updatedSafeAreaInsets.top let top = Inspire.shared.screen.updatedSafeAreaInsets.top
for (i, e) in toasts.enumerated() { for (i, e) in toasts.enumerated() {
@ -391,28 +354,6 @@ internal extension ProHUD {
}) })
DispatchQueue.main.asyncAfter(deadline: .now()+0.001, execute: willUpdateToastsLayout!) 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了")
}
}
} }

View File

@ -8,7 +8,7 @@
import UIKit import UIKit
public extension ProHUD.Toast { public extension Toast {
enum Scene { enum Scene {
/// ///
case `default` case `default`