代码优化

This commit is contained in:
xaoxuu 2022-09-12 17:47:04 +08:00
parent 4b2d9dac3c
commit ebfc53502e
75 changed files with 177 additions and 182 deletions

View File

@ -91,20 +91,34 @@ class AlertVC: ListVC {
}
}
list.add(title: "图标 + 文字 + 按钮") { section in
section.add(title: "图标 + 一段文字 + 自定义浅色按钮") {
Alert(.confirm) { alert in
alert.vm.title = "自定义浅色按钮"
section.add(title: "操作成功") {
Alert(.success(3).title("操作成功").message("这条消息将在3s后消失")).push()
}
section.add(title: "操作失败") {
Alert { alert in
alert.vm = .error.title("操作失败").message("请稍后重试")
alert.add(action: "取消", style: .gray)
alert.add(action: "重试")
}
}
section.add(title: "警告") {
Alert(.warning.message("电量不足,请立即充电")) { alert in
let btn = alert.add(action: "我知道了", style: .filled(color: UIColor.systemYellow))
btn.setTitleColor(.black, for: .normal)
}
}
section.add(title: "确认选择") {
Alert(.confirm.title("请选择颜色")) { alert in
alert.add(action: "红色", style: .light(color: .systemRed))
alert.add(action: "蓝色", style: .light(color: .systemBlue))
}
}
section.add(title: "图标 + 标题 + 正文 + 自定义深色按钮") {
Alert(.note) { alert in
alert.vm.title = "自定义深色按钮"
alert.vm.message = "这是一段正文,长度超出最大宽度时会自动换行"
alert.add(action: "橙色", style: .filled(color: .systemOrange))
alert.add(action: "粉色", style: .filled(color: .systemPink))
alert.add(action: "默认灰色", style: .gray)
section.add(title: "确认删除") {
Alert(.delete) { alert in
alert.vm.title = "确认删除"
alert.vm.message = "此操作无法撤销"
alert.add(action: "取消", style: .gray)
alert.add(action: "删除", style: .destructive)
}
}
}
@ -213,9 +227,13 @@ class AlertVC: ListVC {
let vc = UIViewController()
vc.title = "页面"
vc.view.backgroundColor = .systemYellow
let alert = Alert(.loading.title("正在加载").message("这个弹窗被放在指定的容器中"))
let alert = Alert(.loading.title("正在加载").message("这个弹窗被放在指定容器中"))
alert.add(action: "返回上一页") { alert in
vc.dismiss(animated: true)
}
alert.config.enableShadow = false
self?.present(vc, animated: true)
vc.addChild(alert)
vc.view.addSubview(alert.view)
alert.view.snp.makeConstraints { make in
make.edges.equalToSuperview()

View File

@ -5,12 +5,12 @@
"scale" : "1x"
},
{
"filename" : "prohud.trash@2x.png",
"filename" : "demo.message@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "prohud.trash@3x.png",
"filename" : "demo.message@3x.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -5,12 +5,12 @@
"scale" : "1x"
},
{
"filename" : "prohud.note@2x.png",
"filename" : "demo.note@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "prohud.note@3x.png",
"filename" : "demo.note@3x.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -5,12 +5,12 @@
"scale" : "1x"
},
{
"filename" : "prohud.message@2x.png",
"filename" : "demo.questionmark@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "prohud.message@3x.png",
"filename" : "demo.questionmark@3x.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -5,12 +5,12 @@
"scale" : "1x"
},
{
"filename" : "prohud.trash@2x.png",
"filename" : "demo.trash@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "prohud.trash@3x.png",
"filename" : "demo.trash@3x.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,22 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "prohud.rainbow.circle@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "prohud.rainbow.circle@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -15,17 +15,30 @@ public extension ViewModel {
// static var note: ViewModel {
// ViewModel(icon: UIImage(named: "prohud.note"))
// }
// MARK: note
static var note: ViewModel {
.init(icon: UIImage(named: "demo.note"))
}
static func note(_ seconds: TimeInterval) -> ViewModel {
.init(icon: UIImage(named: "demo.note"), duration: seconds)
}
static var msg: ViewModel {
ViewModel(icon: UIImage(inProHUD: "prohud.message"))
ViewModel(icon: UIImage(named: "demo.message"))
}
static func msg(_ seconds: TimeInterval) -> ViewModel {
ViewModel(icon: UIImage(inProHUD: "prohud.message"), duration: seconds)
ViewModel(icon: UIImage(named: "demo.message"), duration: seconds)
}
static var loading: ViewModel {
let obj = ViewModel(icon: UIImage(named: "prohud.rainbow.circle"))
obj.rotation = .init(repeatCount: .infinity)
return obj
static var delete: ViewModel {
ViewModel(icon: UIImage(named: "demo.trash"))
}
// MARK: confirm
static var confirm: ViewModel {
.init(icon: UIImage(named: "demo.questionmark"))
}
static func confirm(_ seconds: TimeInterval) -> ViewModel {
.init(icon: UIImage(named: "demo.questionmark"), duration: seconds)
}
// static func loading(_ seconds: TimeInterval) -> ViewModel {
// let obj = ViewModel(icon: UIImage(named: "prohud.rainbow.circle"), duration: seconds)
// obj.rotation = .init(repeatCount: .infinity)

View File

@ -18,6 +18,14 @@ class ToastVC: ListVC {
header.titleLabel.text = "ProHUD.Toast"
header.detailLabel.text = message
Toast.Configuration.shared { config in
config.contentViewMask { mask in
mask.backgroundColor = .clear
mask.effect = UIBlurEffect(style: .systemChromeMaterial)
}
}
list.add(title: "默认布局") { section in
section.add(title: "标题 + 正文") {
Toast(.title(title).message(message)).push()
@ -29,7 +37,6 @@ class ToastVC: ListVC {
let s1 = "正在加载"
let s2 = "这条通知4s后消失"
let toast = Toast(.loading(4).title(s1).message(s2))
toast.identifier = "loading"
toast.push()
toast.update(progress: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
@ -39,8 +46,8 @@ class ToastVC: ListVC {
toast.update(progress: 1)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
Toast.find(identifier: "loading") { toast in
toast.vm = .success(2).title("加载成功").message("这条通知2s后消失")
toast.update { toast in
toast.vm = .success(10).title("加载成功").message("这条通知10s后消失")
}
}
}
@ -50,13 +57,13 @@ class ToastVC: ListVC {
}
list.add(title: "事件管理") { section in
section.add(title: "全局点击事件") {
section.add(title: "点击事件") {
let title = "您收到了一条消息"
let message = "这条消息5s后消失点击回复"
Toast(.msg(5).title(title).message(message)) { toast in
let message = "点击通知横幅任意处即可回复"
Toast(.msg.title(title).message(message)) { toast in
toast.onTapped { toast in
toast.pop()
testAlert()
Alert(.success(1).message("操作成功")).push()
}
}
}
@ -87,8 +94,11 @@ class ToastVC: ListVC {
}
}
toast.add(action: "同意") { toast in
Alert.find(identifier: "Dracarys")?.pop()
Alert.find(identifier: "Dracarys", update: { alert in
alert.pop()
})
toast.pop()
Alert(.success(1).message("Good choice!")).push()
}
}
}
@ -124,7 +134,9 @@ class ToastVC: ListVC {
}
}
section.add(title: "移除指定实例") {
Toast.find(identifier: "loading")?.pop()
Toast.find(identifier: "loading") { toast in
toast.pop()
}
}
}

BIN
Resources/Icons.sketch Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
Resources/demo.note@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
Resources/demo.note@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
Resources/demo.trash@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
Resources/demo.trash@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -33,8 +33,13 @@ public class Alert: ProHUD.Controller {
return stack
}()
///
public var imageView = UIImageView()
///
public lazy var imageView: UIImageView = {
let imgv = UIImageView()
imgv.contentMode = .scaleAspectFit
imgv.tintColor = view.tintColor
return imgv
}()
///
public lazy var titleLabel: UILabel = {

View File

@ -29,6 +29,7 @@ extension Alert: DefaultLayout {
return
}
// default layout
//
setupImageView()
@ -53,14 +54,6 @@ extension Alert: DefaultLayout {
self.view.layoutIfNeeded()
}
}
// id .rotate
if let rotation = vm.rotation {
startRotate(rotation)
}
//
vm.timeoutHandler = DispatchWorkItem(block: { [weak self] in
self?.pop()
})
}
@ -133,16 +126,6 @@ extension Alert: DefaultLayout {
extension Alert {
func setupImageView() {
guard let icon = vm.icon else { return }
imageView.image = icon
contentStack.insertArrangedSubview(imageView, at: 0)
imageView.contentMode = .scaleAspectFit
imageView.snp.remakeConstraints { (mk) in
mk.top.left.greaterThanOrEqualTo(contentView).inset(config.padding*2.25)
mk.right.bottom.lessThanOrEqualTo(contentView).inset(config.padding*2.25)
mk.width.equalTo(config.iconSize.width)
mk.height.equalTo(config.iconSize.height)
}
//
stopRotate(animateLayer)
animateLayer = nil
@ -150,6 +133,28 @@ extension Alert {
//
progressView?.removeFromSuperview()
if vm.icon != nil {
imageView.image = vm.icon
if imageView.superview == nil {
contentStack.insertArrangedSubview(imageView, at: 0)
imageView.snp.remakeConstraints { (mk) in
mk.top.left.greaterThanOrEqualTo(contentView).inset(config.padding*2.25)
mk.right.bottom.lessThanOrEqualTo(contentView).inset(config.padding*2.25)
mk.width.equalTo(config.iconSize.width)
mk.height.equalTo(config.iconSize.height)
}
}
if let rotation = vm.rotation {
startRotate(rotation)
}
} else {
if contentStack.arrangedSubviews.contains(imageView) {
contentStack.removeArrangedSubview(imageView)
}
imageView.removeFromSuperview()
}
}
func setupTextStack() {
let titleCount = vm.title?.count ?? 0

View File

@ -85,7 +85,7 @@ extension Alert {
/// HUD
/// - Parameter callback:
func update(handler: @escaping (_ alert: Alert) -> Void) {
public func update(handler: @escaping (_ alert: Alert) -> Void) {
handler(self)
reloadData()
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
@ -96,14 +96,12 @@ extension Alert {
/// HUD
/// - Parameter identifier:
/// - Returns: HUD
public static func find(identifier: String, update handler: ((_ alert: Alert) -> Void)? = nil) -> Alert? {
guard let vc = AlertWindow.alerts.last(where: { $0.identifier == identifier }) else {
return nil
}
@discardableResult public static func find(identifier: String, update handler: ((_ alert: Alert) -> Void)? = nil) -> [Alert] {
let arr = AlertWindow.alerts.filter({ $0.identifier == identifier })
if let handler = handler {
vc.update(handler: handler)
arr.forEach({ $0.update(handler: handler) })
}
return vc
return arr
}
}

View File

@ -104,7 +104,7 @@ public class Configuration: NSObject {
// MARK:
///
public var iconSize = CGSize(width: 48, height: 48)
public var iconSize = CGSize(width: 44, height: 44)
// MARK:
///

View File

@ -105,21 +105,14 @@ public extension ViewModel {
return obj
}
// MARK: note
static var note: ViewModel {
.init(icon: UIImage(inProHUD: "prohud.note"))
}
static func note(_ seconds: TimeInterval) -> ViewModel {
.init(icon: UIImage(inProHUD: "prohud.note"), duration: seconds)
}
// MARK: loading
static var loading: ViewModel {
let obj = ViewModel(icon: UIImage(inProHUD: "prohud.rainbow.circle"))
let obj = ViewModel(icon: UIImage(inProHUD: "prohud.windmill"))
obj.rotation = .init(repeatCount: .infinity)
return obj
}
static func loading(_ seconds: TimeInterval) -> ViewModel {
let obj = ViewModel(icon: UIImage(inProHUD: "prohud.rainbow.circle"), duration: seconds)
let obj = ViewModel(icon: UIImage(inProHUD: "prohud.windmill"), duration: seconds)
obj.rotation = .init(repeatCount: .infinity)
return obj
}
@ -148,12 +141,4 @@ public extension ViewModel {
static var failure: ViewModel { error }
static func failure(_ seconds: TimeInterval) -> ViewModel { error(seconds) }
// MARK: confirm
static var confirm: ViewModel {
.init(icon: UIImage(inProHUD: "prohud.questionmark"))
}
static func confirm(_ seconds: TimeInterval) -> ViewModel {
.init(icon: UIImage(inProHUD: "prohud.questionmark"), duration: seconds)
}
}

View File

@ -12,13 +12,16 @@ extension LoadingAnimation {
/// updateProgress(0)
/// - Parameter progress: 0~1
public func update(progress: CGFloat) {
guard isViewLoaded else { return }
guard let superview = imageView.superview else { return }
if progressView == nil {
let v = ProgressView()
let width = imageView.frame.size.width + ProgressView.lineWidth * 2
let v = ProgressView(frame: .init(origin: .zero, size: .init(width: width, height: width)))
superview.addSubview(v)
v.tintColor = superview.tintColor
v.snp.remakeConstraints { (mk) in
mk.center.equalTo(imageView)
mk.width.height.equalTo(28)
mk.width.height.equalTo(width)
}
progressView = v
}

View File

@ -12,23 +12,41 @@ public class ProgressView: UIView {
var progressLayer = CAShapeLayer()
static var lineWidth: CGFloat { 4 }
public override var tintColor: UIColor! {
didSet {
progressLayer.strokeColor = tintColor.cgColor
}
}
override init(frame: CGRect) {
let lineWidth = Self.lineWidth
//
let maxSize = CGFloat(28)
super.init(frame: .init(x: 0, y: 0, width: maxSize, height: maxSize))
layer.cornerRadius = maxSize / 2
let size = CGFloat.maximum(frame.height, frame.width)
super.init(frame: .init(x: 0, y: 0, width: size, height: size))
layer.cornerRadius = size / 2
layer.masksToBounds = true
//
let radius = maxSize / 2 - 4
backgroundColor = .white
//
let path = UIBezierPath(arcCenter: CGPoint(x: size / 2, y: size / 2), radius: (size - lineWidth) / 2, startAngle: -CGFloat.pi*0.5, endAngle: CGFloat.pi * 1.5, clockwise: true)
let path = UIBezierPath(arcCenter: CGPoint(x: 14, y: 14), radius: radius/2, startAngle: -CGFloat.pi*0.5, endAngle: CGFloat.pi * 1.5, clockwise: true)
//
let bgLayer = CAShapeLayer()
bgLayer.fillColor = UIColor.clear.cgColor
bgLayer.path = path.cgPath
bgLayer.strokeColor = UIColor.white.cgColor
bgLayer.lineWidth = lineWidth
bgLayer.lineCap = .round
bgLayer.strokeStart = 0
bgLayer.strokeEnd = 1
layer.addSublayer(bgLayer)
//
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.path = path.cgPath
progressLayer.strokeColor = tintColor.cgColor
progressLayer.lineWidth = radius
progressLayer.lineWidth = lineWidth
progressLayer.lineCap = .round
progressLayer.strokeStart = 0
progressLayer.strokeEnd = 0
layer.addSublayer(progressLayer)

View File

@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -1,22 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "prohud.questionmark@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "prohud.questionmark@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -1,22 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "prohud.rainbow.circle@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "prohud.rainbow.circle@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@ -5,12 +5,12 @@
"scale" : "1x"
},
{
"filename" : "prohud.privacy@2x.png",
"filename" : "prohud.rainbow@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "prohud.privacy@3x.png",
"filename" : "prohud.rainbow@3x.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -31,15 +31,15 @@ public extension Toast {
}
override var titleFontByDefault: UIFont {
titleFont ?? .systemFont(ofSize: 19, weight: .bold)
titleFont ?? .systemFont(ofSize: 18, weight: .bold)
}
override var boldTextFontByDefault: UIFont {
boldTextFont ?? .systemFont(ofSize: 17, weight: .bold)
boldTextFont ?? .systemFont(ofSize: 16, weight: .bold)
}
override var bodyFontByDefault: UIFont {
bodyFont ?? .systemFont(ofSize: 17, weight: .regular)
bodyFont ?? .systemFont(ofSize: 16, weight: .regular)
}
override var animateDurationForBuildInByDefault: CGFloat {

View File

@ -77,17 +77,7 @@ extension Toast: DefaultLayout {
self?.pop()
})
//
stopRotate(animateLayer)
animateLayer = nil
animation = nil
//
progressView?.removeFromSuperview()
//
if let rotation = vm.rotation {
startRotate(rotation)
}
setupImageView()
}
@ -126,4 +116,20 @@ extension Toast {
contentStack.addArrangedSubview(sup)
}
}
func setupImageView() {
//
stopRotate(animateLayer)
animateLayer = nil
animation = nil
//
progressView?.removeFromSuperview()
imageView.image = vm.icon
if let rotation = vm.rotation {
startRotate(rotation)
}
}
}

View File

@ -40,7 +40,7 @@ extension Toast {
/// HUD
/// - Parameter callback:
func update(handler: @escaping (_ toast: Toast) -> Void) {
public func update(handler: @escaping (_ toast: Toast) -> Void) {
handler(self)
reloadData()
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
@ -51,14 +51,12 @@ extension Toast {
/// HUD
/// - Parameter identifier:
/// - Returns: HUD
@discardableResult public static func find(identifier: String, update handler: ((_ toast: Toast) -> Void)? = nil) -> Toast? {
guard let vc = ToastWindow.windows.last(where: { $0.toast.identifier == identifier })?.toast else {
return nil
}
@discardableResult public static func find(identifier: String, update handler: ((_ toast: Toast) -> Void)? = nil) -> [Toast] {
let arr = ToastWindow.windows.compactMap({ $0.toast }).filter({ $0.identifier == identifier })
if let handler = handler {
vc.update(handler: handler)
arr.forEach({ $0.update(handler: handler) })
}
return vc
return arr
}
}