如何在 Swift 中知道发件人的标识符

Posted

技术标签:

【中文标题】如何在 Swift 中知道发件人的标识符【英文标题】:How to know the sender's identifier in Swift 【发布时间】:2016-02-08 22:17:17 【问题描述】:

我有两个UILabels 和两个UITapGestureRecognizers 在一个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)

我正在使用Segue 推送另一个UIViewController,并且我正在重写PrepareSegue 函数以发送与Sender 标记相对应的所需信息。

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

我的问题是我想知道按下了哪个UILabel,知道我已经在使用tag

【问题讨论】:

什么是UITextLabel?没有这样的事情。 对不起,我编辑了帖子,我的意思是 UILabel 您可以添加一个不同的函数以在点击第二个 UILabel 时调用。然后该函数将调用不同的段标识符,例如 performSegeueWithIdentifier("GoToProfilSeg2") 。然后在您的prepareForSegue 方法中,您只需使用if 语句来处理要执行的segue,即if segue.identifier == "..."" ... 让另一个 segue 显示相同的 View Controller 是没有用的 仅供参考 - 函数和变量名称以小写字母开头并且只有类名以大写字母开头是标准命名约定。 【参考方案1】:

您的GoToProfile: 函数应该正确编写。参数不是“发送者”,而是手势识别器。

func GoToProfil (gestureRecognizer: UITapGestureRecognizer) 

从那里,您可以使用手势识别器的view 属性来确定标签。

但是您似乎有两个相互矛盾的要求。您想知道两个标签中的哪一个被点击,并且您想知道标签在哪一行。

通常您会使用标签的tag 来了解两个标签中的哪一个被点击了。但是您正在使用他们的标签来跟踪该行。

我推荐的解决方案是使用标签来区分两个标签。然后就可以根据标签的边框来计算行了。

有关将单元格子视图的框架转换为单元格的indexPath 的示例代码,请参阅the following answer。

【讨论】:

能否请您展示如何使用视图属性确定标签,这是我所缺少的 我不知道 Swift 但类似let label = gestureRecognizer.view as UILabel。我敢肯定这不是 100% 正确的,但这应该会有所帮助。 取决于您标记 @YasserB 的内容。如果您标记了内部子视图并且容器通过了它将不起作用,因为您检查的视图不是您标记的视图,并且以这种方式使用 viewTags 非常脆弱 我认为@YasserB 希望能够确定是Username 还是SharedUser 标签被点击了。仅仅拥有标签并不能告诉他们它是两者中的哪一个,并且标签已经被用于其他目的,因此无法使用。 @YasserB。我在答案末尾添加了一个链接,显示了此类代码。【参考方案2】:

做出以下假设:

    您正在尝试使用UIView.tag 唯一标识标签 您希望用户名和 SharedUser 有不同的行为

我推荐以下,首先在你的#imports下面定义你的标签

#define kUsername 1
#define kSharedUser 2

然后将它们分配给您的视图

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

然后在你的 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
    

这样您可以轻松简单地确定点击,请注意,如果您有超过 1 个用户名和 SharedUser 标签,这可能会产生不同的结果。然后,您将需要更多#defines 或更改生成标签的方式。

【讨论】:

【参考方案3】:

您可以向 UILabel 添加一个属性来跟踪标签的类型。 (我使用了枚举,因为只有 2 种情况,但它可以是字符串等)

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 )
        
    

现在你可以这样做了:

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

稍后:

switch label.labelDest

    case .Some(.Username):
        // handle user name
        break
    ...

如果您想在标签上使用 .tag 字段,您可以使用不同的技术来查找与标签关联的表格行:(再次使用类扩展)

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
    

现在,通过您的手势识别器操作:

func goToProfil( sender:UIGestureRecognizer! )

    guard let tappedRow = sender.view?.tableRow else  return 
    // handle tap here...

【讨论】:

您也可以在 IB 中使用附加的运行时属性面板设置此属性(我认为这就是所谓的)【参考方案4】:

您可以访问发件人数据,并读取发送给您的对象的标签,就像在这个示例代码中一样。

要唯一标识每一行和每个标签,您可以使用以下内容:

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

有了这个,如果你有一个偶数标签,它的用户名,奇数将是 SharedUser。除以 2 的楼层,您可以将行返回。

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

【讨论】:

sender 不是标签,而是手势识别器。 我的错,我从一个按钮上拿了一个代码,忘记了点击...代码现在是正确的。 这样更好,但 OP 正在使用标签的标签作为 indexPath.row

以上是关于如何在 Swift 中知道发件人的标识符的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中使用 shouldPerformSegueWithIdentifier() 方法

Swift 3 自定义单元格在滚动时更改

Swift:如何以编程方式获取iOS设备的唯一标识符?

如何在 Swift 中按名称/标识符从相机胶卷中获取图像

Swift 中多个未解析的标识符

类型“UIButton”没有成员“发件人”