‘#selector’的参数不能引用全局函数

问题描述 投票:0回答:1

我做了一个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

如何实现点击时关闭?

swift toast
1个回答
0
投票

目标响应选择器。当目标

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 会相当困难。

© www.soinside.com 2019 - 2024. All rights reserved.