How can I fix action button after update Xcode12?

My action buttons stopped working after Xcode update (Xcode 12). When I clicked the buttons, I saw that the functions did not working (like there is no button in there). I could not understand why. How can I fix these functions?

Here my action button function:
Code Block
@objc func addAction(sender: UIButton) {
let indexPath = IndexPath(row: sender.tag, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! customCell
cell.count += 1
cell.countBasketLabel.text = "x\(cell.count)"
let detailGelen = detailsModel[indexPath.row]
selectedItemName.append(detailGelen.itemDetailName!)
selectedItemPrice.append(detailGelen.itemDetailPrice!)
UserDefaults.standard.set(selectedItemName, forKey: "urunadi")
UserDefaults.standard.set(selectedItemPrice, forKey: "urunfiyat")
tableView.reloadData()
}


Here my button code:
Code Block
let addButton: UIButton = {
let button = UIButton(type: .system)
button.setImage(UIImage(named: "add"), for: .normal)
button.tintColor = .black
button.layer.cornerRadius = 5
button.addTarget(self, action: #selector(testdetail.addAction(sender:)), for: .touchUpInside)
return button
}()

How can I fix these functions?

Hard to say anything sure with the limited info.

The method and the property are both defined in the same class?
How your addButton is added to the view controller?

did not working gives no info about what's happening.

Have you put breakpoints? Or some print statements?

addButton on the custom tableview cell. It is all working before the update Xcode.

Add functions on same class but in custom cell view have button's properties.

addButton on the custom tableview cell.

Please show whole code of the custom tableview cell. I cannot make your code work even in older Xcode.
I'm sure the problem isn't caused by this but here my custom tableview cell whole code:

Code Block
class customCell: UITableViewCell {
    
    
    let testdetails = testdetail()
    
    var count = 0
    
     let cellView: UIView = {
               let view = UIView()
               view.backgroundColor = .white
               return view
           }()
           
           let imageOrderForCell: UIImageView = {
               let iv = UIImageView()
               iv.contentMode = .scaleAspectFit
               iv.image = UIImage(named: "checked")
               return iv
           }()
           
           let sepetLabel: UILabel = {
               let label = UILabel()
               label.text = "sepetteki ürün"
               label.textColor = .darkGray
               label.font = UIFont(name:"Comfortaa-Bold", size: 15)
               label.translatesAutoresizingMaskIntoConstraints = false
               return label
           }()
           
           let countBasketLabel: UILabel = {
               let countLabel = UILabel()
               countLabel.text = "x0"
               countLabel.textColor = .orange
               countLabel.font = UIFont(name:"Comfortaa-Bold", size: 15)
               countLabel.translatesAutoresizingMaskIntoConstraints = false
               return countLabel
           }()
           
           let priceBasketLabel: UILabel = {
               let pricelabel = UILabel()
               pricelabel.textColor = .black
               pricelabel.font = UIFont(name:"Comfortaa-Bold", size: 15)
               return pricelabel
           }()
           
           let deleteButton: UIButton = {
               let button = UIButton(type: .system)
               button.setImage(UIImage(named: "delete"), for: .normal)
               button.tintColor = .black
               button.layer.cornerRadius = 5
               button.addTarget(self, action: #selector(testdetail.deleteAction(sender:)), for: .touchUpInside)
               return button
           }()
           lazy var addButton: UIButton = {
               let button = UIButton(type: .system)
               button.setImage(UIImage(named: "add"), for: .normal)
               button.tintColor = .black
               button.layer.cornerRadius = 5
               return button
           }()
           
           override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
               super.init(style: style, reuseIdentifier: reuseIdentifier)
               setup()
           }
           
           required init?(coder aDecoder: NSCoder) {
               fatalError("init(coder:) has not been implemented")
           }
           
           
           func setup() {
               backgroundColor = .clear
               addSubview(cellView)
               cellView.addSubview(sepetLabel)
               cellView.addSubview(priceBasketLabel)
               cellView.addSubview(countBasketLabel)
               cellView.addSubview(addButton)
               cellView.addSubview(deleteButton)
               
               cellView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 4, paddingLeft: 8, paddingBottom: 4, paddingRight: 8, width: 40, height: 40)
               
               sepetLabel.anchor(top: nil, left: cellView.leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 6, paddingBottom: 0, paddingRight: 0, width: 25, height: 25)
               sepetLabel.centerYAnchor.constraint(equalTo: cellView.centerYAnchor).isActive = true
               
               
               priceBasketLabel.anchor(top: nil, left: nil, bottom: nil, right: deleteButton.leftAnchor, paddingTop: 0, paddingLeft: 10, paddingBottom: 0, paddingRight: 20, width: 0, height: 35)
               priceBasketLabel.centerYAnchor.constraint(equalTo: sepetLabel.centerYAnchor).isActive = true
               
               
               countBasketLabel.anchor(top: nil, left: nil, bottom: nil, right: addButton.leftAnchor, paddingTop: 0, paddingLeft: 1, paddingBottom: 0, paddingRight: 1, width: 30, height: 25)
               countBasketLabel.centerYAnchor.constraint(equalTo: sepetLabel.centerYAnchor).isActive = true
        
               
           
               addButton.anchor(top: nil, left: nil, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 2, paddingBottom: 0, paddingRight: 8, width: 30, height: 30)
               addButton.centerYAnchor.constraint(equalTo: sepetLabel.centerYAnchor).isActive = true
               
               deleteButton.anchor(top: nil, left: nil, bottom: nil, right: countBasketLabel.leftAnchor, paddingTop: 0, paddingLeft: 2, paddingBottom: 0, paddingRight: 8, width: 30, height: 30)
               deleteButton.centerYAnchor.constraint(equalTo: sepetLabel.centerYAnchor).isActive = true
           }
}


here my custom tableview cell whole code: 

Your code lacks class header: class ClassName {

And the most important line:
Code Block
button.addTarget(self, action: #selector(testdetail.addAction(sender:)), for: .touchUpInside)

This line does not exist in the whole code version of the addButton.

Which is the right code you are testing?


I replaced that because I try to solve it but in original version is my first post. The problem continues.

Also I have class header of course.
When you post code, you should Paste and Match style to avoid all the extra blank lines.
What is test detail ? Is it a func ?

cellView has no frame defined.
UIView doc states:

init(frame:) - It is recommended that you implement this method. You can also implement custom initialization methods in addition to, or instead of, this method.

So you should change line 8 in something like
Code Block
        let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 40))


Code Block
class customCell: UITableViewCell {
let testdetails = testdetail()
var count = 0
let cellView: UIView = {
let view = UIView()
view.backgroundColor = .white
return view
}()
let imageOrderForCell: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleAspectFit
iv.image = UIImage(named: "checked")
return iv
}()
let sepetLabel: UILabel = {
let label = UILabel()
label.text = "sepetteki ürün"
label.textColor = .darkGray
label.font = UIFont(name:"Comfortaa-Bold", size: 15)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let countBasketLabel: UILabel = {
let countLabel = UILabel()
countLabel.text = "x0"
countLabel.textColor = .orange
countLabel.font = UIFont(name:"Comfortaa-Bold", size: 15)
countLabel.translatesAutoresizingMaskIntoConstraints = false
return countLabel
}()
let priceBasketLabel: UILabel = {
let pricelabel = UILabel()
pricelabel.textColor = .black
pricelabel.font = UIFont(name:"Comfortaa-Bold", size: 15)
return pricelabel
}()
let deleteButton: UIButton = {
let button = UIButton(type: .system)
button.setImage(UIImage(named: "delete"), for: .normal)
button.tintColor = .black
button.layer.cornerRadius = 5
button.addTarget(self, action: #selector(testdetail.deleteAction(sender:)), for: .touchUpInside)
return button
}()
lazy var addButton: UIButton = {
let button = UIButton(type: .system)
button.setImage(UIImage(named: "add"), for: .normal)
button.tintColor = .black
button.layer.cornerRadius = 5
return button
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setup()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setup() {
backgroundColor = .clear
addSubview(cellView)
cellView.addSubview(sepetLabel)
cellView.addSubview(priceBasketLabel)
cellView.addSubview(countBasketLabel)
cellView.addSubview(addButton)
cellView.addSubview(deleteButton)
cellView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 4, paddingLeft: 8, paddingBottom: 4, paddingRight: 8, width: 40, height: 40)
sepetLabel.anchor(top: nil, left: cellView.leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 6, paddingBottom: 0, paddingRight: 0, width: 25, height: 25)
sepetLabel.centerYAnchor.constraint(equalTo: cellView.centerYAnchor).isActive = true
priceBasketLabel.anchor(top: nil, left: nil, bottom: nil, right: deleteButton.leftAnchor, paddingTop: 0, paddingLeft: 10, paddingBottom: 0, paddingRight: 20, width: 0, height: 35)
priceBasketLabel.centerYAnchor.constraint(equalTo: sepetLabel.centerYAnchor).isActive = true
countBasketLabel.anchor(top: nil, left: nil, bottom: nil, right: addButton.leftAnchor, paddingTop: 0, paddingLeft: 1, paddingBottom: 0, paddingRight: 1, width: 30, height: 25)
countBasketLabel.centerYAnchor.constraint(equalTo: sepetLabel.centerYAnchor).isActive = true
addButton.anchor(top: nil, left: nil, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 2, paddingBottom: 0, paddingRight: 8, width: 30, height: 30)
addButton.centerYAnchor.constraint(equalTo: sepetLabel.centerYAnchor).isActive = true
deleteButton.anchor(top: nil, left: nil, bottom: nil, right: countBasketLabel.leftAnchor, paddingTop: 0, paddingLeft: 2, paddingBottom: 0, paddingRight: 8, width: 30, height: 30)
deleteButton.centerYAnchor.constraint(equalTo: sepetLabel.centerYAnchor).isActive = true
}
}

but in original version is my first post.

Then I can assure you that the code in your first post never works even in Xcode 11.
Your issue is not the problem of Xcode 12, but the modification you have done to the once-worked code.

Also I have class header of course.

You should have included it.

I replaced that because I try to solve

I guess you have replaced too much from the code which once worked.

The line that I have shown as the most important would never work neither in Xcode 11 nor in Xcode 12.

Code Block
button.addTarget(self, action: #selector(testdetail.deleteAction(sender:)), for: .touchUpInside)


Code Block
button.addTarget(self, action: #selector(testdetail.addAction(sender:)), for: .touchUpInside)


Inside the instance method of CustomCell, self represents an instace of CustomCell.
It does not have a method named deleteAction(sender:) nor addAction(sender:). So, these lines just cause runtime error (even in Xcode 11).
(I have renamed customCell to CustomCell, as type identifiers of Swift should start with Capital letter.)
I have the same issue. It seems that buttons in a UItableViewCell behave differently between iOS 13 and iOS 14. I guess the touch events are not properly received by the buttons. Probably the UITableView is intercepting them?
How do you present the view with the UITableView ?

If presentation mode is Automatic (allowing to dismiss the view with a swipe down), then it may cause problem for some gestures.

Could it be the case here ?

Could you check presentation mode and try to replace by Full screen, just to confirm ?
I am having the same issue. Here is my boiler plate code to recreate it.

This is the ViewController Class:

Code Block swift
import UIKit
class SecondScreen: UITableViewController {
private let anotherButtonIdentifier = "AnotherButtonCell"
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(AnotherCustomCell.self, forCellReuseIdentifier: anotherButtonIdentifier)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: anotherButtonIdentifier, for: indexPath) as! AnotherCustomCell
return cell
}
}




Here is the custom Cell code:

Code Block swift
import UIKit
class AnotherCustomCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.backgroundColor = .red
let button:UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.backgroundColor = .black
button.setTitle("Button", for: .normal)
button.addTarget(self, action:#selector(self.handleButtonClick(sender:)), for: .touchUpInside)
self.addSubview(button)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func handleButtonClick(sender: UIButton) {
print("Button click")
}
}

I used two simulators. The first one 13.5 works as expected and the console puts out the output. The second simulator with 14.0 doesnt allow me to click the button. Nothing happens. Seems that the button is in the background or something. Any ideas?
I have this issue as well, but only have the problem when building with Xcode 12 on iOS 14. Building the same code from Xcode 11.5 or running on 13.5 works as expected.
@klo

 Here is my boiler plate code to recreate it.

Thanks for showing the working code. It runs fine when built with Xcode 11.7 (in simulator 13.7 and 14.0), and the button does not respond when built with Xcode 12.
Now, I can examine what's going on.
@klo

Seems that the button is in the background or something. Any ideas?

As far as I tried, adding this line to init(style:reuseIdentifier:) made the button respond to tap.
Code Block
self.contentView.isUserInteractionEnabled = true

Please try with your actual project.
@OOPer

As far as I tried, adding this line to init(style:reuseIdentifier:) made the button respond to tap.
Code Block

Code Block
self.contentView.isUserInteractionEnabled = true
AWESOME! That fixed the issue for me. In my opinion this seems to be a bug. I tried your code and then looked if they changed the default behavior. Apparently it is already enough to call:

Code Block swift
print("Userinteraction: \(self.contentView.isUserInteractionEnabled)")

By printing out the value, without changing it, already allows me to use the buttons again. Seems like a bug to me, what do you think @OOper?

@klo

Seems like a bug to me, what do you think @OOper?

Same as you. I'm not sure if Apple's engineer wants to call it a bug, but at least, this sort of significant change should be documented.
You should better send a feedback to Apple.
This thread is exceptionally difficult to follow, but I will echo that I believe I am seeing the same issue in our app. There are numerous instances throughout our app where we have UITableViewCell subclasses that embed buttons within their contentView AND also allow selection such that didSelectRow... will get triggered when the larger cell content is tapped.

As has been described by other posters, the way these buttons/cells are set up has not changed since we began compiling against Xcode 12, but it does seem that their underlying behavior has. Previously, the button taps would be accepted as expected; however, now, the button taps are ignored and the tap goes through to the cell itself.

Here's what I have determined so far:
  • As suggested by other posters, this is in some way tied to contentView.isUserInteractionEnabled. According to the documentation for that property, it is still supposed to default to true.

  • This issue can be worked around by simply accessing contentView.isUserInteractionEnabled - like by calling: print("\(contentView.isUserInteractionEnabled)")

  • The workaround will only work when the access is done outside of the initializer. I have tried numerous orderings and combinations, and it seems that if I directly access this property from within the code block of the initializer, it has no effect. However, if the access is made within a function called by the initializer, it does work.

A sample is attached below to further demonstrate the issue and my workaround:

Code Block swift
protocol MyCellDelegate: class {
    func didTapButtonInCell(_ cell: MyTableViewCell)
}
class MyTableViewCell: UITableViewCell {
    weak var delegate: MyCellDelegate?
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
// Adding either of these calls here does NOT work:
        // contentView.isUserInteractionEnabled = true
        // print("\(contentView.isUserInteractionEnabled)")
        setupMyButton()
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    private func setupMyButton() {
// Adding either of these calls here DOES work:
       // contentView.isUserInteractionEnabled = true
       // print("\(contentView.isUserInteractionEnabled)")
        let button: UIButton = {
            $0.setTitle("Tap me!", for: .normal)
            return $0
        }(UIButton(type: .system))
        button.addTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside)
        // Add the button to the `contentView` and lay it out accordingly...
    }
    @objc private func didTapButton(_ sender: UIButton) {
        delegate?.didTapButtonInCell(self)
    }
}







had this problem too. turns out I was adding subviews to tableView cell.
all my custom views are covered by contentView.
adding subviews to contentView should solve the problem.

I also get same this issue, and after some hours debug and find this line is cause:
self.contentView.backgroundColor = [UIColor clearColor];

I just commented it and the issue was fixed! I don't know why it only happen on xcode 12
@dangnv
Does it only occur with buttons in cellView or also with other buttons ?

I have tested with buttons in a view, it works with clear background.
I solved my issue by doing this,

Old - (below iOS 14)

[cell addSubview:__];

New code - (iOS 14)

[cell.contentView addSubview:
__];
How can I fix action button after update Xcode12?
 
 
Q