如何检查是不是从 Swift 的 XIB 文件中单击了按钮?

Posted

技术标签:

【中文标题】如何检查是不是从 Swift 的 XIB 文件中单击了按钮?【英文标题】:How to check if button is clicked from XIB file in Swift?如何检查是否从 Swift 的 XIB 文件中单击了按钮? 【发布时间】:2017-11-09 18:11:51 【问题描述】:

我遇到以下情况。我使用 XIB 文件创建了一个自定义 UIView。我连接了一个继承自 UIView 的 VC,并将其添加到 File Owner 属性中。使用@IBOutlet 连接两个按钮并将两个按钮连接到相同的@IBAction 方法,这将切换背景颜色,以获得布尔效果。默认情况下不选择任何按钮。

在我的 ViewController.swift 文件中,它与 Storyboard 中的视图控制器连接,我将其作为子视图添加到我的 UICollectionView 单元格中。

根据我的两个模型类(MessagesPermissionMessage),我确定按钮的文本应该是什么。

我的愿望是给按钮添加功能,所以当点击按钮一时,它会触发功能A,如果选择按钮二,就会触发功能B。

此时我不知道应该在哪里执行此逻辑,以确定应该触发哪个函数。另外因为我可以创建相同BooleanView.xib 的不同实例,所以我不能将函数添加到该XIB 文件的文件所有者类中,对吗?

我试图在UICollectionViewdidSelectItemAt 方法中单击按钮,但我无法访问以编程方式添加的自定义UIView,称为BooleanView()

根据单击的按钮向每个实例按钮添加功能的正确方法和方法是什么?

在我的示例中,我想确定当前实例的选定按钮是Manual 还是GPS。如果是手动,它会做一些事情,比如在我的控制台中打印一个文本,如果选择了 GPS,我想调用我存储在自定义单独类/处理程序中的 LocationManager 的初始化程序。

这个函数放在UICollectionViewcellForItemAt方法里面:

        if message is PermissionMessage 
            let bool = BooleanView()
            bool.frame = CGRect(x: 60, y: estimatedFrame.height + 15, width: estimatedFrame.width + 15 + 8, height: bool.frame.height)

            let permissionType = (message as! PermissionMessage).getTypeOfPermission()

            switch permissionType 
            case .camera:
                print("Case: camera")

                bool.leftButton.setTitle("Yes", for: .normal)
                bool.rightButton.setTitle("No", for: .normal)
                cell.addSubview(bool)
            case .location:
                print("Case: location")

                bool.leftButton.setTitle("Manual", for: .normal)
                bool.rightButton.setTitle("GPS", for: .normal)
                cell.addSubview(bool)
            

        

注意:message 变量是indexPath.row 的选定数组条目。

添加到我BooleanView.xib的自定义UIView类:

class BooleanView: UIView 

    @IBOutlet var contentView: UIView!
    @IBOutlet weak var leftButton: UIButton!
    @IBOutlet weak var rightButton: UIButton!

    //MARK: Initialization
    override init(frame: CGRect) 
        super.init(frame: frame)

        // Load the nib named 'CardView' into memory, finding it in the main bundle.
        Bundle.main.loadNibNamed("BooleanView", owner: self, options: nil)

        self.frame = contentView.frame


        addSubview(contentView)

        // Style the custom view
        contentView.backgroundColor = UIColor.clear
        leftButton.layer.cornerRadius = (leftButton.frame.height / 2)
        rightButton.layer.cornerRadius = (rightButton.frame.height / 2)

    

    required init(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)!

    

    @IBAction func pressedButton(_ sender: UIButton) 

        if sender.backgroundColor == Constants.BOOL_BUTTON.enabled 
            return
        

        sender.backgroundColor = Constants.BOOL_BUTTON.enabled
        sender.titleLabel?.font = UIFont(name: Constants.FONTS.bold, size: (sender.titleLabel?.font.pointSize)!)

        if sender.tag == 0 
            self.rightButton.backgroundColor = Constants.BOOL_BUTTON.disabled
            self.rightButton.titleLabel?.font = UIFont(name: Constants.FONTS.regular, size: (self.rightButton.titleLabel?.font.pointSize)!)
         else 
            self.leftButton.backgroundColor = Constants.BOOL_BUTTON.disabled
            self.leftButton.titleLabel?.font = UIFont(name: Constants.FONTS.regular, size: (self.leftButton.titleLabel?.font.pointSize)!)
        
    

【问题讨论】:

Swift 3- How to get button in UICollectionViewCell work的可能重复 您需要一个集合视图单元子类来获取视图控制器和布尔视图之间的信息。我会在布尔视图中添加某种状态枚举并将其镜像到单元格中。 你能举个例子吗? @theMikeSwan。我查看了可能重复的帖子,并试图让它与委托协议一起工作,但我认为这在我基于 XIB 文件创建的自定义 UIView 类中不起作用.. @Caspert - 您在问题中发布的代码现在有效吗?也就是说,它正确设置了字体和颜色?您需要一种方法来告诉视图控制器该按钮已被点击? 【参考方案1】:

首先,您需要一种方法来传达按下了哪个按钮(如果有的话),enum 将为此工作:

enum BooleanViewState 
    case none
    case left
    case right

接下来,您的BooleanView 需要能够将其状态传达给相关方。鉴于您只关心给定布尔视图在特定时刻的状态,最简单的方法是使用计算属性。此外,您当前进入视图以设置按钮标题的方法并不是最佳实践,因此我们还将添加一种替代方法:

class BooleanView: UIView 
    var boolViewState: BooleanViewState 
        get 
            if leftButton.backgroundColor == Constants.BOOL_BUTTON.enabled 
                return .left
             else if rightButton.backgroundColor == Constants.BOOL_BUTTON.enabled 
                return .right
             else 
                return .none
            
        
    

    var buttonTitles = (leftTitle: "", rightTitle: "") 
        didSet 
            leftButton.setTitle(buttonTitles.leftTitle, for: .normal)
            rightButton.setTitle(buttonTitles.rightTitle, for: .normal)
        
    

    // The rest of you existing class

您可能需要将didSet 添加到获取标题的两个按钮的插座中。 可能在按钮存在之前设置标题。

接下来,您需要从使用默认的 UICollectionViewCell 切换到可以保存 BooleanView 并来回传递内容的自定义子类:

class BooleanViewCell: UICollectionViewCell 
    @IBOutlet private var boolView: BooleanView!

    var boolViewState: BooleanViewState 
        get 
            return boolView.boolViewState
        
    
    var buttonTitles = (leftTitle: "", rightTitle: "") 
        didSet 
            boolView.buttonTitles = buttonTitles
        
    

您需要更改 cellForItemAt 方法中的一些代码

    if message is PermissionMessage 
        let permissionType = (message as! PermissionMessage).getTypeOfPermission()

        switch permissionType 
        case .camera:
            print("Case: camera")

            cell.buttonTitles = (leftTitle: "Yes", rightTitle: "No")
        case .location:
            print("Case: location")

            cell.buttonTitles = (leftTitle: "Manual", rightTitle: "GPS")
        
    

最后要做的是从didSelectItemAt中的单元格中读取boolState

guard let cell = collectionView.cellForItem(at: indexPath) as? BooleanViewCell else  return 
let theState = cell.boolState
// React to the state as needed

这确实意味着您需要将通用 UIView 添加到情节提要中的原型集合视图单元格,将其类设置为 BooleanView 并将其连接到 BooleanViewCell 中的插座。

尽管我在没有编译器的情况下完成了所有这些工作,但它应该会为您解决所有问题,因此我不能保证我没有拼错或遗漏任何东西。

【讨论】:

以上是关于如何检查是不是从 Swift 的 XIB 文件中单击了按钮?的主要内容,如果未能解决你的问题,请参考以下文章

错误:在 swift 中使用 xib 文件注册自定义 tableView 单元格

你如何在 Swift 中展示来自 Xib 的 VC?

将数据从 TableViewController 传递到 XIB 文件而不使用 Segues-Swift 3

如何使用Swift 3从Xib加载NSView

Swift:iOS - 通过第三类将数据从 ViewController 传递到 xib 文件

如何创建从集合单元 xib 文件到集合视图控制器的出口