[英]Passing arguments to selector in Swift
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.我使用此模型对象为图钉图像提供地图上的坐标,因此我认为将对象发送到手势处理程序对我来说很容易。
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()
or或者
func doSomething(sender: Any)
or或者
func doSomething(sender: Any, forEvent event: UIEvent)
where…在哪里…
The
sender
parameter 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.此外, #selector()
应该包含 func 签名,并且不包含传递的参数。 So for…因此对于…
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 modelObj
is 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
中引用它
Step 1: create the custom object of the sender.步骤 1:创建发件人的自定义对象。
step 2: add properties you want to change in that a custom object of the sender第 2 步:在发件人的自定义对象中添加要更改的属性
step 3: typecast the sender in receiving function to a custom object and 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:也在故事板中设置自定义类
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 object of 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 object and 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
}
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;这是我的 2 美分,相同但不同的技术; a minimal version.一个最小的版本。
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.使用它,确保将自定义变量设置为 bargin。 Using a simple label here, note the last line, important labels are not normally interactive.在这里使用一个简单的标签,注意最后一行,重要的标签通常不是交互式的。
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.并使用它设置动作,注意我想使用纯枚举,但Objective 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.你有它。
cell.btn.tag = indexPath.row //setting tag
cell.btn.addTarget(self, action: #selector(showAlert(_ :)), for: .touchUpInside)
@objc func showAlert(_ sender: UIButton){
print("sender.tag is : \(sender.tag)")// getting tag's value
}
Just create a custom class of UITapGestureRecognizer =>只需创建一个自定义类 UITapGestureRecognizer =>
import UIKit
class OtherUserProfileTapGestureRecognizer: UITapGestureRecognizer {
let userModel: OtherUserModel
init(target: AnyObject, action: Selector, userModel: OtherUserModel) {
self.userModel = userModel
super.init(target: target, action: action)
}
}
And then create UIImageView extension =>然后创建 UIImageView 扩展 =>
import UIKit
extension UIImageView {
func gotoOtherUserProfile(otherUserModel: OtherUserModel) {
isUserInteractionEnabled = true
let gestureRecognizer = OtherUserProfileTapGestureRecognizer(target: self, action: #selector(self.didTapOtherUserImage(_:)), otherUserModel: otherUserModel)
addGestureRecognizer(gestureRecognizer)
}
@objc internal func didTapOtherUserImage(_ recognizer: OtherUserProfileTapGestureRecognizer) {
Router.shared.gotoOtherUserProfile(otherUserModel: recognizer.otherUserModel)
}
}
Now use it like =>现在像 => 一样使用它
self.userImageView.gotoOtherUserProfile(otherUserModel: OtherUserModel)
You can use an UIAction
instead:您可以改用UIAction
:
self.imageView.addAction(UIAction(identifier: UIAction.Identifier("imageClick")) { [weak self] action in
self?.handleTap(modelObj)
}, for: .touchUpInside)
that may be a terrible practice but I simply add whatever I want to restore to这可能是一种糟糕的做法,但我只是添加了我想要恢复的任何内容
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: [:])
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.