将参数传递给 Swift 中的选择器
Passing arguments to selector in Swift
我正在以编程方式将 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
}
我遇到的第一个问题是“'#selector' 的参数不引用'@Objc' 方法、属性 或初始化程序。
太棒了,所以我将@objc 添加到 handleTap 签名中:
@objc func handleTap(modelObj: Model) {
// Doing stuff with model object here
}
现在我收到错误“方法无法标记为@objc,因为参数的类型无法在 Objective-C 中表示。
这只是一张建筑物地图的图像,一些图钉图像指示了兴趣点的位置。当用户点击其中一个引脚时,我想知道他们点击了哪个兴趣点,并且我有一个模型对象来描述这些兴趣点。我使用这个模型对象来为 pin 图像提供它在地图上的坐标,所以我认为将对象发送到手势处理程序对我来说很容易。
看来您误解了几件事。
当使用target/action时,函数签名必须有特定的形式…
func doSomething()
或
func doSomething(sender: Any)
或
func doSomething(sender: Any, forEvent event: UIEvent)
哪里……
The sender
parameter is the control object sending the action message.
在你的例子中,发件人是 UITapGestureRecognizer
此外,#selector()
应包含 func 签名,并且不包含传递的参数。所以对于...
func handleTap(sender: UIGestureRecognizer) {
}
你应该有……
let gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
假设func和gesture都在一个view controller中,其中modelObj
是一个属性/ivar,不需要通过gesture recogniser传递,可以参考它在 handleTap
第 1 步:创建发件人的自定义对象。
第 2 步:在发件人
的自定义对象中添加要更改的属性
第 3 步:将接收函数中的发送方强制转换为 自定义对象 并访问这些属性
例如:
如果您想发送字符串或任何自定义对象,请单击按钮
第 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
}
}
步骤 2-a:在情节提要中也设置自定义 class
步骤 2-b:使用自定义 class 创建该按钮的 IBOutlet,如下所示
@IBOutlet weak var btnFullRemote: CustomButton!
第 3 步:在发件人
的自定义对象中添加要更改的属性
btnFullRemote.name = "Nik"
btnFullRemote.customObject = customObject
btnFullRemote.customObject2 = customObject2
btnFullRemote.addTarget(self, action: #selector(self.btnFullRemote(_:)), for: .touchUpInside)
第 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
}
这可能是一种糟糕的做法,但我只是将我想要恢复的任何内容添加到
button.restorationIdentifier = urlString
和
@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: [:])
}
}
}
Swift 5.0 iOS 13
我同意 Ninad 的一个很好的回答。这是我的 2 美分,相同但不同的技术;最小版本。
创建一个自定义 class,将枚举抛给 keep/make 尽可能维护代码。
enum Vs: String {
case pulse = "pulse"
case precision = "precision"
}
class customTap: UITapGestureRecognizer {
var cutomTag: String?
}
使用它,确保将自定义变量设置到 bargin 中。这里使用一个简单的标签,注意最后一行,重要的标签通常不会交互。
let precisionTap = customTap(target: self, action: #selector(VC.actionB(sender:)))
precisionTap.customTag = Vs.precision.rawValue
precisionLabel.addGestureRecognizer(precisionTap)
precisionLabel.isUserInteractionEnabled = true
并使用它设置操作,注意我想使用纯枚举,但 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
}
}
给你了。
只需创建自定义 class 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)
}
}
然后创建 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)
}
}
像这样使用吧=>
self.userImageView.gotoOtherUserProfile(otherUserModel: OtherUserModel)
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
}
您可以改用 UIAction
:
self.imageView.addAction(UIAction(identifier: UIAction.Identifier("imageClick")) { [weak self] action in
self?.handleTap(modelObj)
}, for: .touchUpInside)
我正在以编程方式将 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
}
我遇到的第一个问题是“'#selector' 的参数不引用'@Objc' 方法、属性 或初始化程序。
太棒了,所以我将@objc 添加到 handleTap 签名中:
@objc func handleTap(modelObj: Model) {
// Doing stuff with model object here
}
现在我收到错误“方法无法标记为@objc,因为参数的类型无法在 Objective-C 中表示。
这只是一张建筑物地图的图像,一些图钉图像指示了兴趣点的位置。当用户点击其中一个引脚时,我想知道他们点击了哪个兴趣点,并且我有一个模型对象来描述这些兴趣点。我使用这个模型对象来为 pin 图像提供它在地图上的坐标,所以我认为将对象发送到手势处理程序对我来说很容易。
看来您误解了几件事。
当使用target/action时,函数签名必须有特定的形式…
func doSomething()
或
func doSomething(sender: Any)
或
func doSomething(sender: Any, forEvent event: UIEvent)
哪里……
The
sender
parameter is the control object sending the action message.
在你的例子中,发件人是 UITapGestureRecognizer
此外,#selector()
应包含 func 签名,并且不包含传递的参数。所以对于...
func handleTap(sender: UIGestureRecognizer) {
}
你应该有……
let gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
假设func和gesture都在一个view controller中,其中modelObj
是一个属性/ivar,不需要通过gesture recogniser传递,可以参考它在 handleTap
第 1 步:创建发件人的自定义对象。
第 2 步:在发件人
的自定义对象中添加要更改的属性第 3 步:将接收函数中的发送方强制转换为 自定义对象 并访问这些属性
例如: 如果您想发送字符串或任何自定义对象,请单击按钮
第 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
}
}
步骤 2-a:在情节提要中也设置自定义 class
步骤 2-b:使用自定义 class 创建该按钮的 IBOutlet,如下所示
@IBOutlet weak var btnFullRemote: CustomButton!
第 3 步:在发件人
的自定义对象中添加要更改的属性btnFullRemote.name = "Nik"
btnFullRemote.customObject = customObject
btnFullRemote.customObject2 = customObject2
btnFullRemote.addTarget(self, action: #selector(self.btnFullRemote(_:)), for: .touchUpInside)
第 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
}
这可能是一种糟糕的做法,但我只是将我想要恢复的任何内容添加到
button.restorationIdentifier = urlString
和
@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: [:])
}
}
}
Swift 5.0 iOS 13
我同意 Ninad 的一个很好的回答。这是我的 2 美分,相同但不同的技术;最小版本。
创建一个自定义 class,将枚举抛给 keep/make 尽可能维护代码。
enum Vs: String {
case pulse = "pulse"
case precision = "precision"
}
class customTap: UITapGestureRecognizer {
var cutomTag: String?
}
使用它,确保将自定义变量设置到 bargin 中。这里使用一个简单的标签,注意最后一行,重要的标签通常不会交互。
let precisionTap = customTap(target: self, action: #selector(VC.actionB(sender:)))
precisionTap.customTag = Vs.precision.rawValue
precisionLabel.addGestureRecognizer(precisionTap)
precisionLabel.isUserInteractionEnabled = true
并使用它设置操作,注意我想使用纯枚举,但 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
}
}
给你了。
只需创建自定义 class 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)
}
}
然后创建 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)
}
}
像这样使用吧=>
self.userImageView.gotoOtherUserProfile(otherUserModel: OtherUserModel)
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
}
您可以改用 UIAction
:
self.imageView.addAction(UIAction(identifier: UIAction.Identifier("imageClick")) { [weak self] action in
self?.handleTap(modelObj)
}, for: .touchUpInside)