0
votes

My first post so I am hoping I am doing the right thing.

I have a custom UIView that contains an array of custom UIButtons.

I have overridden func draw(_ rect: CGRect) which has the following code:

  override func draw(_ rect: CGRect) {

    // remove all buttons currently on the bar
    self.subviews.forEach { $0.removeFromSuperview() }

    // process all buttons that are not hidden
    var i = 0
    for btn in buttons {
      if !btn.button.isHidden {
        self.addSubview(btn.button)

        // set constraints with SnapKit
        btn.button.snp.makeConstraints { (c) in
          c.size.equalTo(buttonSize)
          c.left.equalToSuperview().offset(padding.width + (isVertical ? 0 : (i * buttonSize.width)))
          c.top.equalToSuperview().offset(padding.height + (isVertical ? (i * buttonSize.height) : 0))
        }

        i += 1
      }
    }

    // set button bar's constraints
    snp.updateConstraints { (c) in
      if isVertical {
        c.height.equalTo(max(visibleCount, 1) * buttonSize.height + 2 * padding.height)
      } else {
        c.width.equalTo(max(visibleCount, 1) * buttonSize.width + 2 * padding.width)
      }
    }

  }

Whenever I perform a setNeedsLayout(), it performs as expected however it also recenters a UIImage in the same superview.

This causes issues since the UIImage can be panned around and recentering it is not expected behaviour.

I have tested the code above by commenting different sections and have found that it is when it positions the buttons themselves that it causes this behaviour.

Of course, this is not the behaviour that I want.

Any help/ideas/suggestions would be most welcome.

The order of subview additions in the ViewController is ...

  private func setupViews() {
    view.backgroundColor = .green

    view.addSubview(mapDisplay)
    view.addSubview(contextMenu)
    view.addSubview(FloatingMenu)

  }
1
What specifically are you trying to accomplish? It feels to me like you are misusing drawRect... at it's most basic, you should be drawing (bezier paths, maybe layers) but removing subviews or changing constraints? They usually belong elsewhere. - dfd
All the code is in the draw func for simplicity's sake. It was in separate funcs like setupLayout, updateLayout etc. As to what I am trying to accomplish? The button bar grows/shrinks as buttons are made visible/hidden. This functionality is based on user selections. So for example, if they click on Edit, then two buttons controlling editing are revealed, with the Edit button turning editing off and hiding those two buttons. All of that works - my problem is that it somehow is affecting a completely unrelated UIImageView. - UrsaTeddy

1 Answers

0
votes

I have worked the problem out myself after pulling apart my code.

It turns out that I had an empty constraint placeholder for the UIImageView in question and that SnapKit takes an empty constraint as an explicit directive to "remove" all constraints and reset the item in question back to "zero" when something else calls for an update.

I think this behaviour is erroneous since my UIView was a sibling subview in the View Controller, however there it is ... so doing something like

mapDisplay.snp.makeConstraints { (c) in

}

will make the UIImageView (mapDisplay) snap back to screen centre for some reason when the UIView updates the button positions.

Should post this on their gitHub I guess.