I have made a Toast function as below
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")
}
Calling it as below.
showToast(toastTitle: "error", toastText: "toast text comes here", type: .error)
Toast is showing and goes away in 3 seconds which is not an issue.
I want to remove Toast if anyone click on it. So I add a button. However issue coming when adding target on it.
Error I get is as below.
Argument of '#selector' cannot refer to global function 'clickedDefaultToast()'
If I add @objc for function, I get error as
@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
How can I achieve this to dismiss when clicked?
Targets respond to selectors. It doesn't make sense to pass a selector of
clickedDefaultToast, when the targetcurrentViewdoesn't respond to it, regardless of whether Swift allows you to do this.Selectors are usually methods declared in a class (and instances of that class would respond to the selector), and so Swift has the
#selector(...)syntax to let you get aSelectorfrom an instance method.If you just want to call a global function when the button is clicked,
addActioninstead ofaddTarget. This allows you to just pass a Swift closure instead of a selector.Otherwise, you would need to change your design to use target-action pairs. The usage could be something like:
You'd move
showToastandclickedDefaultToastinto a newToastclass. You would useselfas the target of the button, andselfcan respond to theclickedDefaultToastselector.In my opinion, this design is better because you can also store the currently displayed toast
UIViewin theToastinstance, so dismissing it is trivial - just remove theUIViewfrom its superview. With your current design, finding the currently displayed toast would be rather hard.