在界面构建器中放错位置的IBDesignable元素需要手动更新帧

时间:2017-02-21 15:09:44

标签: ios swift xcode interface-builder ibdesignable

我正在使用单选按钮视图,并已在https://github.com/paulicelli/RadioButton上的github上传了一个测试项目

这基本上是UIStackView的子类,具有IBInspectable数量的按钮来创建一些单选按钮。

在设备上工作,但是当我打开Interface Builder时,我总是看到按钮错位,直到我改变按钮数或间距。您可以在view1中看到问题,然后在view2中找到正确的视图。

view 1 view 2

问题: 如何在打开按钮时告诉“界面”构建器正确定位按钮?

这是代码:

import UIKit

// ROUNDBUTTON
final class RoundButton: UIButton {

  var borderWidth: CGFloat = 2.0
  var primaryColor: UIColor = UIColor.blue

  var primaryColorWithAlpha: UIColor {
    return primaryColor.withAlphaComponent(0.25)
  }

  override public var buttonType: UIButtonType {
    return .custom
  }

  override public func layoutSubviews() {
    super.layoutSubviews()
    self.layer.cornerRadius = bounds.size.width * 0.5
    self.clipsToBounds = true
    setupColors()
  }

  func setupColors() {
    switch self.state {
    case UIControlState.normal:
      super.backgroundColor = .white
      self.setTitleColor(primaryColor, for: state)
      self.layer.borderColor = primaryColor.cgColor
      self.layer.borderWidth = borderWidth
    default:
      super.backgroundColor = primaryColorWithAlpha
      self.setTitleColor(.white, for: state)
    }
  }

}
// END OF ROUNDBUTTON

// PROTOCOL
@objc protocol RadioButtonsViewDelegate {
  @objc optional func didSelectButton(_ aButton: RoundButton?)
}
// END OF PROTOCOL

// RADIOBUTTONSVIEW
@IBDesignable
class RadioButtonsView: UIStackView {

  var shouldLetDeselect = true

  var buttons = [RoundButton]()

  weak var delegate : RadioButtonsViewDelegate? = nil

  private(set) weak var currentSelectedButton: RoundButton? = nil

  @IBInspectable
  var number: Int = 2 {
    didSet {
      number = max(number, 2)
      setupButtons()
    }
  }

  func setupButtons() {
    if !buttons.isEmpty {
      buttons.forEach { self.removeArrangedSubview($0) }
      buttons.removeAll()
    }

    for i in 0..<self.number {
      let button = RoundButton()
      button.setTitle("\(i)", for: .normal)
      button.addTarget(self, action: #selector(pressed(_:)),
                       for: UIControlEvents.touchUpInside)
      buttons.append(button)
    }
  }

  func pressed(_ sender: RoundButton) {
    if (sender.isSelected) {
      if shouldLetDeselect {
        sender.isSelected = false
        currentSelectedButton = nil
      }
    }else {
      buttons.forEach { $0.isSelected = false }
      sender.isSelected = true
      currentSelectedButton = sender
    }
    delegate?.didSelectButton?(currentSelectedButton)
  }

  override init(frame: CGRect) {
    super.init(frame: frame)
    setupButtons()
  }

  required init(coder: NSCoder) {
    super.init(coder: coder)
    setupButtons()
  }

  override var intrinsicContentSize: CGSize {
    return CGSize(width: self.bounds.width,
                  height: UIViewNoIntrinsicMetric)
  }

  override func layoutSubviews() {
    self.translatesAutoresizingMaskIntoConstraints = false

    buttons.forEach { self.addArrangedSubview($0) }

    let constraints: [NSLayoutConstraint] = {
      var constraints = [NSLayoutConstraint]()
      constraints.append(NSLayoutConstraint(item: buttons[0],
                                                 attribute: NSLayoutAttribute.width,
                                                 relatedBy: NSLayoutRelation.equal,
                                                 toItem: self,
                                                 attribute: NSLayoutAttribute.height,
                                                 multiplier: 1,
                                                 constant: 0)
        )
      for i in 1..<buttons.count {
        constraints.append(NSLayoutConstraint(item: buttons[i],
                                            attribute: NSLayoutAttribute.width,
                                            relatedBy: NSLayoutRelation.equal,
                                            toItem: buttons[i - 1],
                                            attribute: NSLayoutAttribute.width,
                                            multiplier: 1,
                                            constant: 0)
        )
      }
      return constraints
    }()

    self.addConstraints(constraints)
  }

}
// END OF RADIOBUTTONSVIEW

修改 根据@dfd的要求,我也尝试过:

@IBInspectable
var number: Int {
  get {
    setupButtons()
    return self.number
  }
  set {
    self.number = max(newValue, 2)
    setupButtons()
  }
}

我在加载Interface Builder时遇到了2个错误:

  1. 错误:IB Designables:无法呈现和更新ViewController(BYZ-38-t0r)的自动布局状态:代理程序崩溃
  2. 错误:IB Designables:无法更新自动布局状态:代理崩溃

0 个答案:

没有答案