ios 将参数传递给 Swift 中的选择器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43251708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:03:13  来源:igfitidea点击:

Passing arguments to selector in Swift

iosswiftuikitselector

提问by mike

I'm programmatically adding a UITapGestureRecognizer to one of my views:

我以编程方式将 UITapGestureRecognizer 添加到我的一个视图中:

let gesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(modelObj:myModelObj)))

self.imageView.addGestureRecognizer(gesture)

func handleTap(modelObj: Model) {
  // Doing stuff with model object here
}

The first problem I encountered was "Argument of '#selector' does not refer to an '@Objc' method, property, or initializer.

我遇到的第一个问题是“'#selector' 的参数不引用'@Objc' 方法、属性或初始值设定项。

Cool, so I added @objc to the handleTap signature:

很酷,所以我在 handleTap 签名中添加了 @objc:

@objc func handleTap(modelObj: Model) {
  // Doing stuff with model object here
}

Now I'm getting the error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C.

现在我收到错误“方法不能被标记@objc,因为参数的类型不能在Objective-C中表示。

It's just an image of the map of a building, with some pin images indicating the location of points of interest. When the user taps one of these pins I'd like to know which point of interest they tapped, and I have a model object which describes these points of interest. I use this model object to give the pin image it's coordinates on the map so I thought it would have been easy for me to just send the object to the gesture handler.

它只是建筑物地图的图像,其中一些图钉图像指示了兴趣点的位置。当用户点击这些图钉之一时,我想知道他们点击了哪个兴趣点,并且我有一个描述这些兴趣点的模型对象。我使用这个模型对象来为图钉图像提供它在地图上的坐标,所以我认为将对象发送到手势处理程序对我来说很容易。

回答by Ashley Mills

It looks like you're misunderstanding a couple of things.

看起来你误解了几件事。

When using target/action, the function signature has to have a certain form…

使用target/action 时,函数签名必须具有某种形式……

func doSomething(sender: Any)

or

或者

func doSomething(sender: Any, forEvent event: UIEvent)

where…

在哪里…

The senderparameter is the control object sending the action message.

sender参数是发送动作消息的控制对象。

In your case, the sender is the UITapGestureRecognizer

在您的情况下,发件人是 UITapGestureRecognizer

Also, #selector()should contain the func signature, and does NOT include passed parameters. So for…

此外,#selector()应该包含 func 签名,并且不包含传递的参数。因此对于…

func handleTap(sender: UIGestureRecognizer) {

}

you should have…

你应该有…

let gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))

Assuming the func and the gesture are within a view controller, of which modelObjis a property / ivar, there's no need to pass it with the gesture recogniser, you can just refer to it in handleTap

假设 func 和手势在一个视图控制器中,它modelObj是一个属性/ivar,没有必要用手势识别器传递它,你可以在handleTap

回答by Ninad Kambli

Step 1: create the custom object of the sender.

步骤1:创建发件人的自定义对象。

step 2: add properties you want to change in that a custom objectof the sender

第 2 步:添加要更改的属性,即发件人的自定义对象

step 3: typecast the sender in receiving function to a custom objectand access those properties

第 3 步:将接收函数中的发送者类型转换为自定义对象并访问这些属性

For eg: on click of the button if you want to send the string or any custom object then

例如:如果您想发送字符串或任何自定义对象,则单击按钮

step 1: create

第 1 步:创建

class CustomButton : UIButton {

    var name : String = ""
    var customObject : Any? = nil
    var customObject2 : Any? = nil

    convenience init(name: String, object: Any) {
        self.init()
        self.name = name
        self.customObject = object
    }
}

step 2-a: set the custom class in the storyboard as well

步骤 2-a:也在故事板中设置自定义类

enter image description here

在此处输入图片说明

step 2-b: Create IBOutlet of that button with a custom class as follows

步骤 2-b:使用自定义类创建该按钮的 IBOutlet,如下所示

@IBOutlet weak var btnFullRemote: CustomButton!

step 3: add properties you want to change in that a custom objectof the sender

第 3 步:添加要更改的属性,即发件人的自定义对象

btnFullRemote.name = "Nik"
btnFullRemote.customObject = customObject
btnFullRemote.customObject2 = customObject2
btnFullRemote.addTarget(self, action: #selector(self.btnFullRemote(_:)), for: .touchUpInside)

step 4: typecast the sender in receiving function to a custom objectand access those properties

第 4 步:将接收函数中的发送者类型转换为自定义对象并访问这些属性

@objc public func btnFullRemote(_ sender: Any) {

var name : String = (sender as! CustomButton).name as? String

var customObject : customObject = (sender as! CustomButton).customObject as? customObject

var customObject2 : customObject2 = (sender as! CustomButton).customObject2 as? customObject2

}

回答by user3069232

Swift 5.0 iOS 13

斯威夫特 5.0 iOS 13

I concur a great answer by Ninad. Here is my 2 cents, the same and yet different technique; a minimal version.

我同意由一个伟大的答案Ninad。这是我的 2 美分,相同但不同的技术;一个最小版本。

Create a custom class, throw a enum to keep/make the code as maintainable as possible.

创建一个自定义类,抛出一个枚举以保持/使代码尽可能可维护。

enum Vs: String {
  case pulse = "pulse"
  case precision = "precision"
} 

class customTap: UITapGestureRecognizer {
  var cutomTag: String?
}

Use it, making sure you set the custom variable into the bargin. Using a simple label here, note the last line, important labels are not normally interactive.

使用它,确保将自定义变量设置到 bargin 中。在这里使用一个简单的标签,注意最后一行,重要的标签通常不具有交互性。

let precisionTap = customTap(target: self, action: #selector(VC.actionB(sender:)))
precisionTap.customTag = Vs.precision.rawValue
precisionLabel.addGestureRecognizer(precisionTap)
precisionLabel.isUserInteractionEnabled = true

And setup the action using it, note I wanted to use the pure enum, but it isn't supported by Objective C, so we go with a basic type, String in this case.

并使用它设置操作,注意我想使用纯枚举,但目标 C 不支持它,因此我们使用基本类型,在这种情况下为 String。

@objc func actionB(sender: Any) {
// important to cast your sender to your cuatom class so you can extract your special setting.
  let tag = customTag as? customTap
  switch tag?.sender {
    case Vs.pulse.rawValue:
      // code
    case Vs.precision.rawValue:
      // code
    default:
      break
    }
}

And there you have it.

你有它。

回答by Chucky

that may be a terrible practice but I simply add whatever I want to restore to

这可能是一种糟糕的做法,但我只是添加了我想要恢复的任何内容

button.restorationIdentifier = urlString

button.restorationIdentifier = urlString

and

@objc func openRelatedFact(_ sender: Any) {
        if let button = sender as? UIButton, let stringURL = factButton.restorationIdentifier, let url = URL(string: stringURL) {
            if UIApplication.shared.canOpenURL(url) {
                UIApplication.shared.open(url, options: [:])
            }
        }

    }