Swift普通班无法从UIButton接收触摸事件

时间:2018-12-01 16:03:40

标签: ios iphone swift uikit

我正在尝试为一组按钮创建一个单独的类,以处理一次只能选择一个按钮(单选按钮)的逻辑

这里的逻辑并不重要。点击这些按钮之一时,我只是无法收到touchUpIndside事件。

我将目标设置为self(自定义RadionButtonsController类),但是此类无法接收事件。

我试图将UIResponder添加为超类。但是仍然无法在此类中接收事件。

这是我的代码:

import UIKit

class RadioButtonsController: UIResponder
{
    var buttons = [UIButton]()
    var selectedValue: String?

    init(numberOfButtons: Int, titles: [String], values: [String])
    {
        guard titles.count == numberOfButtons && values.count == numberOfButtons else
        {
            fatalError("number of items in `titles` and `values` must equal to the `numberOfButtons`")
        }

        super.init()

        for i in 0..<numberOfButtons
        {
            let button = UIButton(type: .system)
            button.setTitle(titles[i], for: .normal)
            button.backgroundColor = [UIColor.red, UIColor.blue, UIColor.gray, UIColor.yellow].randomElement()
            button.addTarget(self, action: #selector(radioButtonSelected(sender:)), for: .touchUpInside)
            buttons.append(button)
        }
    }

    @objc private func radioButtonSelected(sender: UIButton)
    {   
        print("Selected Button: \(sender)") // this is will never get printed
    }


}

然后在表格视图单元格中使用此按钮控制器。在cellForRowAtIndexPath中:

let itemOptionsCell = tableView.dequeueReusableCell(withIdentifier: "ItemOptionsCell", for: indexPath) as! ItemOptionsTableViewCell
let itemOption = logicController.item.options[indexPath.row]
itemOptionsCell.optionsTitleLabel.text = itemOption.name

let radioButtonsController = RadioButtonsController(numberOfButtons: itemOption.values.count,
                                                             titles: itemOption.values.map({ $0.name }),
                                                             values: itemOption.values.map({ $0.valueID }))
for button in radioButtonsController.buttons
{
    itemOptionsCell.buttonsStackView.addArrangedSubview(button)
}

return itemOptionsCell

按钮似乎已被单击,但是方法radionButtonSelected(snder:)从未被调用。

2 个答案:

答案 0 :(得分:0)

如果要创建不使用任何外部Pod的RadioButton 您可以使用以下代码:

import Foundation
import UIKit
class HRadioButton: UIButton {
    @IBOutlet var otherButtons: [HRadioButton]!
    var hSelected = false {
        didSet {
            if hSelected {
                if imageView != nil{
                     self.setImage(checkedImage, for: .normal)
                }else{
                    self.setImage(checkedImage, for: .normal)
                    print("image null")
                }
                if self.otherButtons != nil {
                    for button in self.otherButtons {
                        button.hSelected = false
                        button.imageView?.image = self.unCheckedImage
                    }
                } else {
                    print("Button is null ")
                }
            }
        }
    }
    var checkedImage: UIImage!, unCheckedImage: UIImage!

    override func awakeFromNib() {
        super.awakeFromNib()
        checkedImage = #imageLiteral(resourceName: "ic_radio_button_checked").maskWithColor(color: tintColor)
        unCheckedImage = #imageLiteral(resourceName: "ic_radio_button_unchecked").maskWithColor(color: tintColor)
        setImage(unCheckedImage, for: .normal)
        alignImageRight()

        self.onTap {
             self.imageView?.image = self.checkedImage
            self.hSelected = true
            if self.otherButtons != nil {
                for button in self.otherButtons {
                    button.hSelected = false
                    button.imageView?.image = self.unCheckedImage
                }
            } 

        }
    }
}




extension UIImage {

    func maskWithColor(color: UIColor) -> UIImage? {
        let maskImage = cgImage!

        let width = size.width
        let height = size.height
        let bounds = CGRect(x: 0, y: 0, width: width, height: height)

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
        let context = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)!

        context.clip(to: bounds, mask: maskImage)
        context.setFillColor(color.cgColor)
        context.fill(bounds)

        if let cgImage = context.makeImage() {
            let coloredImage = UIImage(cgImage: cgImage)
            return coloredImage
        } else {
            return nil
        }
    }

}



extension UIView {

    // In order to create computed properties for extensions, we need a key to
    // store and access the stored property
    fileprivate struct AssociatedObjectKeys {
        static var tapGestureRecognizer = "MediaViewerAssociatedObjectKey_mediaViewer"
    }

    fileprivate typealias Action = (() -> Void)?

    // Set our computed property type to a closure
    fileprivate var tapGestureRecognizerAction: Action? {
        set {
            if let newValue = newValue {
                // Computed properties get stored as associated objects
                objc_setAssociatedObject(self, &AssociatedObjectKeys.tapGestureRecognizer, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
            }
        }
        get {
            let tapGestureRecognizerActionInstance = objc_getAssociatedObject(self, &AssociatedObjectKeys.tapGestureRecognizer) as? Action
            return tapGestureRecognizerActionInstance
        }
    }

    // This is the meat of the sauce, here we create the tap gesture recognizer and
    // store the closure the user passed to us in the associated object we declared above
    public func onTap(action: (() -> Void)?) {
        self.isUserInteractionEnabled = true
        self.tapGestureRecognizerAction = action
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture))
        self.addGestureRecognizer(tapGestureRecognizer)
    }

    // Every time the user taps on the UIImageView, this function gets called,
    // which triggers the closure we stored
    @objc fileprivate func handleTapGesture(sender: UITapGestureRecognizer) {
        if let action = self.tapGestureRecognizerAction {
            action?()
        } else {
            print("no action")
        }
    }

}

从xcode故事板ui中将HRadioButton类分配为Button类,然后您将在Connection Inspector image of Connection Inspector Icon in Xcode中找到otherButtons。

在xcode中,您会发现otherButtons出现在这里,因此将其拖放到其他按钮上

,然后在要使其成为“广播组”的所有按钮上重复此过程 例如 我有A按钮,B按钮,C按钮 我将类分配给A Button,然后将其他按钮从Connection Inspector拖放到B和C Button 然后将Class To B分配给B按钮,并使otherButtons引用A,C Buttons,依此类推。

稍后您可以从hSelected属性中获取选定的Btn

答案 1 :(得分:0)

问题是您的代码创建了一个RadioButtonsController对象,然后将其丢弃。因此,您的按钮无人可发送操作。