Yasser B. February 2016

How to know the sender's identifier in Swift

I have two UILabels with two UITapGestureRecognizers in a UITableViewCell.

cell.Username.tag = indexPath.row
cell.SharedUser.tag = indexPath.row
let tapGestureRecognizer2 = UITapGestureRecognizer(target:self, action:"GoToProfil:")
let tapGestureRecognizer3 = UITapGestureRecognizer(target:self, action:"GoToProfil:")
cell.Username.userInteractionEnabled = true
cell.Username.addGestureRecognizer(tapGestureRecognizer2)
cell.SharedUser.userInteractionEnabled = true
cell.SharedUser.addGestureRecognizer(tapGestureRecognizer3)

func GoToProfil (sender: AnyObject!) {
    self.performSegueWithIdentifier("GoToProfilSegue", sender: sender)
}

I'm using a Segue to push another UIViewController, and I'm overriding the PrepareSegue function to send the needed information corresponding to the Sender tag.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {

    let ProfilView = segue.destinationViewController as! Profil
    ProfilView.hidesBottomBarWhenPushed = true
    ProfilView.title = posts[sender.view!.tag].User?.objectForKey("Name") as? String
    ProfilView.User = posts[sender.view!.tag].User
}

My problem is that I want to know which UILabel was pressed, knowing that I'm already using tag.

Answers


rmaddy February 2016

Your GoToProfile: function should be written properly. The parameter isn't the "sender", it's the gesture recognizer.

func GoToProfil (gestureRecognizer: UITapGestureRecognizer) {
}

From there, you can determine the label by using the view property of the gesture recognizer.

But you seem to have two conflicting requirements. You want to know which of the two labels was tapped and you want to know which row the label is in.

Normally you would use the label's tag to know which of the two labels was tapped. But you are using their tags to track the row.

The solution I recommend is to use the tag to differentiate the two labels. Then you can calculate the row based on the frame of the label.

See the following answer for sample code that translates the frame of a cell's subview to the cell's indexPath.


UlyssesR February 2016

You can access the sender data, and read the tag of the object that send you, like in this sample code.

To uniquely identify each row and each label, you can use something like this:

  • cell.Username.tag = (indexPath.row*2)
  • cell.SharedUser.tag = (indexPath.row*2)+1

With this, if you have a even tag, its the Username, odd will be the SharedUser. Dividing by the floor of 2 you can have the row back.

@IBOutlet weak var test1: UILabel!
@IBOutlet weak var test2: UILabel!



override func viewWillAppear(animated: Bool) {
    test1.tag = 1
    test2.tag = 2

    test1.userInteractionEnabled = true
    test2.userInteractionEnabled = true

    self.test1.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleSingleTap:"))
    self.test2.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleSingleTap:"))
}

func handleSingleTap(sender: UITapGestureRecognizer) {
    print(sender.view?.tag)
}


CStreel February 2016

Making the following assumptions:

  1. You are trying to uniquely identify the label using UIView.tag
  2. You want different behaviour for Username & SharedUser

I recommend the following, first define your tags below your #imports

#define kUsername 1
#define kSharedUser 2

Then assign them to your views

cell.Username.tag = kUsername
cell.SharedUser.tag = kSharedUser

Then in your prepareSegue

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    int tag = [sender.view!.tag]
    if (tag == kUsername) {
       //Username logic
    } else if(tag == kSharedUser)  {
       //Shared User Logic
    }
}

This way you can easily and simply determine tap, Note this might have different results if you have more then 1 Username & SharedUser labels. Then you will either need more #defines or change how you generate your tags.


nielsbot February 2016

You can add a property to UILabel to track the label's type. (I used an enum since there's just 2 cases, but it could be a string, etc.)

enum LabelDest : String
{
    case Username = "Username"
     case SharedUser = "SharedUser"
}

extension UILabel
{
    struct Static {
        static var key = "labelDest"
    }
    var labelDest:LabelDest? {
        set { objc_setAssociatedObject( self, &Static.key, newValue?.rawValue, .OBJC_ASSOCIATION_COPY_NONATOMIC )
        }
        get {
            guard let val = objc_getAssociatedObject( self, &Static.key ) as? String else { return nil }
            return LabelDest( rawValue:val )
        }
    }
}

Now you can just do this:

let label = UILabel()
label.labelDest = .Username

Later:

switch label.labelDest
{
    case .Some(.Username):
        // handle user name
        break
    ...

If you want to use the .tag field on your labels you can use a different technique to find the table row associated with a label: (again using class extensions)

extension UIView
{
    var enclosingTableViewCell:UITableViewCell? {
        return superview?.enclosingTableViewCell
    }
    var enclosingTableView:UITableView? {
        return superview?.enclosingTableView
    }
}

extension UITableViewCell
{
    var enclosingTableViewCell:UITableViewCell? {
        return self
    }
}

extension UITableView
{
    var enclosingTableView:UITableView? {
        return self
    }
}

extension UIView {
    var tableRow:Int? {
        guard let cell = self.enclosingTableViewCell else { return nil }
        return self.enclosingTableView?.indexPathForCell( cell )?.row
    }
}

Now, from your gesture recognizer action:

func goToProfil( sender:UIGestureRecognizer! )
{
    guard let tappedRow = sender.view?.tableRow else { return }
    // handle tap here...
}

Post Status

Asked in February 2016
Viewed 1,434 times
Voted 4
Answered 4 times

Search




Leave an answer