Passing arguments to selector in Swift

后端 未结 6 574
闹比i
闹比i 2020-11-27 03:14

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

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


        
相关标签:
6条回答
  • 2020-11-27 03:28

    Just create a custom class of 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 =>

    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)
    
    0 讨论(0)
  • 2020-11-27 03:33

    Step 1: create the custom object of the sender.

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

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

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

    step 1: create

    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

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

    @IBOutlet weak var btnFullRemote: CustomButton!
    

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

    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

    @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
    
    }
    
    0 讨论(0)
  • 2020-11-27 03:34

    Swift 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.

    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.

    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.

    @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.

    0 讨论(0)
  • 2020-11-27 03:36

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

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

    func doSomething(sender: Any)
    

    or

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

    where…

    The sender parameter is the control object sending the action message.

    In your case, the sender is the UITapGestureRecognizer

    Also, #selector() should contain the func signature, and does NOT include passed parameters. 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

    0 讨论(0)
  • 2020-11-27 03:37
    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
    }
    
    0 讨论(0)
  • 2020-11-27 03:48

    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: [:])
                }
            }
    
        }
    
    0 讨论(0)
提交回复
热议问题