我做了一个Toast功能如下
CommonFunctions.swift
import UIKit
func showToast(toastTitle: String, toastText: String, type : ToastType, position : ToastPosition = .center, style : ToastStyle = .defaultToast){
if (style == .defaultToast) {
if let foundView = topVC?.view.viewWithTag(toastTagNumber) {
foundView.removeFromSuperview()
}
toastTimer?.invalidate()
toastTimer = nil
if let currentView : UIView = topVC?.view {
let toastView : UIView = UIView()
currentView.addSubview(toastView)
toastView.translatesAutoresizingMaskIntoConstraints = false
toastView.tag = toastTagNumber
toastView.backgroundColor = AppColors.topBarBackgroundColor
toastView.fillHorizontally(padding: 10*iPhoneFactorX)
toastView.Bottom == currentView.Bottom - (bottomBarInnerHeight + safeAreaBottomHeight + (10*iPhoneFactorX))
toastView.addRadius(radius: 15*iPhoneFactorX)
let toast_headerLabel : UILabel = UILabel()
toastView.addSubview(toast_headerLabel)
toast_headerLabel.translatesAutoresizingMaskIntoConstraints = false
toast_headerLabel.Top == toastView.Top + (10*iPhoneFactorX)
toast_headerLabel.fillHorizontally(padding: 5*iPhoneFactorX)
toast_headerLabel.adjustDefaultLabel(fontColor: AppColors.whiteColor_FFFFFF, fontSize: 15, fontType: .bold)
toast_headerLabel.text = toastTitle
toast_headerLabel.isHidden = toastTitle.isEmpty
toast_headerLabel.textAlignment = .center
let toast_textLabel : UILabel = UILabel()
toastView.addSubview(toast_textLabel)
toast_textLabel.translatesAutoresizingMaskIntoConstraints = false
toast_textLabel.Top == toast_headerLabel.Bottom + (10*iPhoneFactorX)
toast_textLabel.fillHorizontally(padding: 5*iPhoneFactorX)
toast_textLabel.adjustDefaultLabel(fontColor: AppColors.whiteColor_FFFFFF, fontSize: 14)
toast_textLabel.text = toastText
toast_textLabel.textAlignment = .center
toastView.Bottom == toast_textLabel.Bottom - (10*iPhoneFactorX)
toastTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(toastDismissDuration), repeats: false) { (Timer) in
hideToast()
}
let toast_button : UIButton = UIButton(type: .custom)
toastView.addSubview(toast_button)
toast_button.translatesAutoresizingMaskIntoConstraints = false
toast_button.setTitle("", for: .normal)
toast_button.fillContainer()
toast_button.backgroundColor = .clear
// problem comes here
toast_button.addTarget(currentView, action: #selector(clickedDefaultToast), for: .touchUpInside)
toastView.addSubview(toast_button)
}
}
}
func clickedDefaultToast() {
print("fapa=clickedDefaultToast==0001")
}
如下调用。
showToast(toastTitle: "error", toastText: "toast text comes here", type: .error)
Toast 会显示并在 3 秒内消失,这不是问题。
如果有人点击 Toast,我想删除它。所以我添加了一个按钮。然而,在其上添加目标时会出现问题。
我得到的错误如下。
Argument of '#selector' cannot refer to global function 'clickedDefaultToast()'
如果我为函数添加
@objc
,我会得到错误
@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
如何实现点击时关闭?
目标响应选择器。当目标
clickedDefaultToast
不响应时,传递currentView
的选择器是没有意义的,无论Swift是否允许你这样做。
选择器通常是在类中声明的方法(该类的实例将响应选择器),因此 Swift 具有
#selector(...)
语法,可让您从 instance方法获取
Selector
。
addAction
而不是 addTarget
。这允许您只传递 Swift 闭包而不是选择器。
toast_button.addAction(UIAction { clickedDefaultToast() }, for: .touchUpInside)
否则,您将需要更改设计以使用目标操作对。用法可能类似于:
// declare a Toast property at the class level
let toast = Toast()
// in some method...
toast.showToast(...)
您会将
showToast
和 clickedDefaultToast
转移到新的 Toast
班级。您可以使用 self
作为按钮的目标,并且 self
可以响应 clickedDefaultToast
选择器。
在我看来,这种设计更好,因为您还可以将当前显示的 toast
UIView
存储在 Toast
实例中,因此忽略它很简单 - 只需从其超级视图中删除 UIView
即可。根据您当前的设计,找到当前显示的 toast 会相当困难。