在Swift中将参数传递给选择器

时间:2017-04-06 09:54:51

标签: ios swift uikit selector

我是以编程方式将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中表示。

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

6 个答案:

答案 0 :(得分:55)

看起来你误解了一些事情。

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

func doSomething(sender: Any)

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

其中...

  

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

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

此外,#selector()应包含func签名,并且不包含传递的参数。所以......

func handleTap(sender: UIGestureRecognizer) {

}
你应该......

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

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

答案 1 :(得分:11)

步骤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:使用自定义类创建该按钮的IBOutlet,如下所示

@IBOutlet weak var btnFullRemote: CustomButton!

步骤2-b:同样在故事板中设置自定义类

enter image description here

第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

}

答案 2 :(得分:2)

只需创建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)

答案 3 :(得分:-1)

Swift 5.0 iOS 13

我同意Ninad的回答。这是我的2美分,相同但又不同的技术;最低版本。

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

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

class customTap: UITapGestureRecognizer {
  var cutomTag: String?
}

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

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
    }
}

在那里,你有它。

答案 4 :(得分:-1)

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
}

答案 5 :(得分:-2)

这可能是一个糟糕的做法,但我只添加要恢复到的内容

db.collection.aggregate([ { $replaceRoot: { newRoot: { $arrayToObject: [[ { k: "$name", v: { $setUnion: [ ["$ph.phone"], ["$alt_ph.phone"] ] } } ]] } } } ])

button.restorationIdentifier = urlString