EXC_BAD_ACCESS 使用 IBInspectable

EXC_BAD_ACCESS Using IBInspectable

我正在尝试使用 IBInspectable 为我的视图添加边框。

extension UIView {

    private func getBorder(integer: Int) -> UIRectEdge {
        if integer == 1 {
            return .top
        } else if integer == 2 {
            return .left
        } else if integer == 3 {
            return .right
        } else if integer == 4 {
            return .bottom
        }
        return .all

    }

    @IBInspectable var border: Int? {
        get {
            return self.border
        }
        set (value) {
            self.border = value
            for v in addBorder(edges: self.getBorder(integer: self.border!)) {
                self.addSubview(v)
            }
        }
    }

    @IBInspectable var borderColor: UIColor? {
        get {
            return self.borderColor
        }
        set (value) {
            self.borderColor = value //EXC_BAD_ACCESS here
            for v in addBorder(edges: self.getBorder(integer: self.border!), color: borderColor!) {
                self.addSubview(v)
            }
        }
    }

    private func addBorder(edges: UIRectEdge, color: UIColor = UIColor.white, thickness: CGFloat = 1) -> [UIView] {
        ...
    }
}

崩溃发生在 self.borderColor = value 行(在 borderColorset 行)。

它在调试日志中所说的只是 (lldb)。崩溃本身说:

Thread 1: EXC_BAD_ACCESS (code=2, address=0x7fff53cc5fe8)

这是我的故事板:

我该如何解决这个问题?谢谢!

你那里有一个无限递归,这是导致崩溃的原因。基本上在 borderColor 的 setter 中,您为相同的 属性 调用 setter,导致无限递归。

发生这种情况是因为 class 扩展不允许存储属性,因此 Swift 不会为您的 属性 生成后备存储,而是将其视为计算 属性,并在您尝试设置 属性.

时调用 setter

目前我能想到的有两种解决方案,可以解决您的问题:

  1. Subclass UIView,在那里添加两个属性,更新 IB 中的 class 以匹配新 class.
  2. 的名称
  3. 在您的 UIView 访问器 (objc_setAssociatedObject()/ objc_getAssociatedObject()) 中使用关联对象,而不是直接引用 iVar。你不需要 subclass 和更新你的 xibs,但是这个解决方案比第一个解决方案有点混乱。