0

I have the the following custom cell:

class MyCell: UITableViewCell {

    func configure(title1: String, title2: String) {
        backgroundColor = .red

        let myView = MyView(frame: frame)
        myView.button1.setTitle(title1, for: .normal)
        myView.button2.setTitle(title2, for: .normal)

        addSubview(myView)
    }
}

and the custom view:

class MyView: UIView {
    var button1: UIButton!
    var button2: UIButton!

    override var backgroundColor: UIColor? {
        didSet {
            guard UIColor.clear.isEqual(backgroundColor) else { return }
            button1.setTitle("asldkfa")
            button1.backgroundColor = .blue
            button2.backgroundColor = .yellow
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        button1 = UIButton()
        button2 = UIButton()
        button1.backgroundColor = .purple
        button2.backgroundColor = .brown
        backgroundColor = .gray

        let stackView = UIStackView(); stackView.distribution = .fill; stackView.alignment = .fill
        stackView.addArrangedSubview(button1)
        stackView.addArrangedSubview(button2)

        addSubview(stackView)
    }
}

I initialized the cell view within my tableView:cellForRowAt method like this:

let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyCell
cell.configure(title1: "Foo", title2: "Bla")

I get the following output in my tableView:

table cell

Every time the color of MyView is changed externally (for example when clicking on the cell), I want to colours of the buttons to change – that is why I have overridden the didSet observer of backgroundColor in MyView. Eventually I want those colours to be random, but here I am just trying to change button1.backgroundColor = .blue.

It does not work, the color of the buttons does not change. I have even tried changing the tintColor and it also does not work. Changing the title with button1.setTitle(...) does work, so I have no idea what is happening.

Does anyone have an idea?

Thanks in advance.

EDIT

When I build the app, add button1.setTitle("asldkfa", for: .normal) inside the didSet, and click on the cell, this is the output:

enter image description here

Meaning that the backgroundColor is set, as the title does change, just not the colours.

IMPORTANT: There is no other code where the backgroundColor is changed explicitly and the didSelectRowAt method is not even implemented. When a cell is selected, the backgroundColor of its subviews is automatically updated, so that is how I am changing the color at the moment, by selecting the cell.

regina_fallangi
  • 2,080
  • 2
  • 18
  • 38
  • 2
    I don't see anywhere in your code that you actually modifying the background color of myView. – inokey Aug 30 '18 at 15:31
  • As I mention in the answer, just click on the cell. The `backgroundColor` is change to the selected one. – regina_fallangi Aug 30 '18 at 15:31
  • Can you show your selection code please? – inokey Aug 30 '18 at 15:33
  • I don't have selection code, I build the app, select the cell and it changes the color because it propagates it. – regina_fallangi Aug 30 '18 at 15:33
  • First, You probably might want to think about adding Button in your configure Method in your cell. Second, aren't you reloading your cell? – Abhishek Harsha Aug 30 '18 at 15:33
  • 1
    Okay, now I see the issue. Chaning background color of a cell doesn't mean it changes background color of myView added as a subview to a cell. You either need to override `setSelected` in your tableView cell, or use `didSelectRowAt` delegate method and change background color of `myView` programmatically. – inokey Aug 30 '18 at 15:34
  • @inokey please ready my question, when I add `button1.setTitle("blabla", for: .normal)` inside the `didSet` function it *changes* the title, meaning the `backgroundColor` does get set on click. – regina_fallangi Aug 30 '18 at 15:36
  • try putting your color changing code to `layoutSubviews()` method in `myView` – inokey Aug 30 '18 at 15:48
  • Have you checked the `frame` of `myView`? `let myView = MyView(frame: frame)` doesn't seem right. – Henny Lee Aug 30 '18 at 15:52
  • @inokey that does not work :( The buttons work just fine, I can change sizes and title this way, only not background color. – regina_fallangi Aug 30 '18 at 15:53
  • are those buttons are plain UIButtons or they're custom buttons? Is there any chance that their class is somehow overriding the backgroundColor behaviour? Have you tried to put on a breakpoint in myView `init` method to check whether is not accidentally recreated, and thus resetting all the changes? – inokey Aug 30 '18 at 15:56
  • They are plain `UIButtons`. I just tried setting the breakpoint and it does not get triggered after clicking the cell. Also set a breakpoint in `cellForRowAt` and it also doesn't get triggered. Only the breakpoint inside `didSet` is triggered after clicking the cell. – regina_fallangi Aug 30 '18 at 15:59
  • where do you add the stackview as a subview? why are the buttons in the output picture u added are purple and brown? are you sure you are looking at the right cell? maybe you are looking at a cell from storyboard? – Eyal Aug 30 '18 at 16:15
  • 1
    I managed to recreate the behaviour in the example, and still cannot figure out what's happening there. It seems like background colours of view is completely wiped out on selection, changing it to nil, and then back to the gray color. – inokey Aug 30 '18 at 16:17
  • use dispatch async – Puji Wahono Aug 06 '19 at 03:42

2 Answers2

2

Updated: Instead of using the UIButton's backgroundColor property, you actually want to be using setBackgroundImage(_:for:). You can use an extension on UIImage (extension example here) to create an image from a color and that should work well for what you're trying to do.

Your resulting configuration code should look something like:

button1.setBackgroundImage(.image(with: .red), for: .normal)
Dan L
  • 88
  • 7
  • `It is worth nothing that by setting a value for the property in the initializer of MyView after calling super.init(frame:) you will have already triggered didSet` -- this part – inokey Aug 30 '18 at 16:28
  • The background colors can change as often as needed (will be random colors)so that’s not the problem. I don’t have code for cell selection. Will test out this code in a while. Thanks. – regina_fallangi Aug 30 '18 at 16:32
  • You may have simply omitted this in your example code, but as @Eyal mentioned, we also can't see where you're adding the StackView as a subview. Make sure you're not missing that :) – Dan L Aug 30 '18 at 16:36
  • I had omitted that code because I thought it was not relevant. I have added it now. I also don't change the color every time, just when the cell is selected (`backgroundColor == UIColor.clear`). The code I update with your answer is here https://gist.github.com/lfcj/698b6983f10380016e21735391af8f2a and it also does not manage to change just the backgroundColor of the buttons. – regina_fallangi Aug 31 '18 at 07:00
  • I just posted an update (#2) abve — missed something before that is most likely the issue. – Dan L Aug 31 '18 at 15:59
  • You should change your answer to set the `button1.backgroundImage(imageWithSolidColor, for: .normal)` within the `configure` method. Where the `imageWithSolidColor` is created according to first answer in https://stackoverflow.com/questions/26542035/create-uiimage-with-solid-color-in-swift Please update and I will mark as answer. – regina_fallangi Sep 03 '18 at 11:58
-3

Actually, the problem is it didSet you added the color so while changing it will remain the same you should do like this

 override var backgroundColor: UIColor? {
    didSet {
        button1.backgroundColor = backgroundColor
        button2.backgroundColor = backgroundColor
    }
}