我正在尝试为一组按钮创建一个单独的类,以处理一次只能选择一个按钮(单选按钮)的逻辑
这里的逻辑并不重要。点击这些按钮之一时,我只是无法收到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:)
从未被调用。
答案 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对象,然后将其丢弃。因此,您的按钮无人可发送操作。