为什么IBInspectables的didSet顺序不尊重层次结构?

时间:2018-01-29 14:24:53

标签: swift

鉴于这两个类:

class A: UIView{
    var setMe: Int!
    @IBInspectable var setMePlease: Int = 0{
        didSet{
            setMe = setMePlease
        }
    }
}

class B: A{
    @IBInspectable var control: Bool = false{
        didSet{
            let a = setMe + 1
        }
    }
}

如果您首先在界面构建器中设置controlsetMePlease的值,它将会崩溃。为什么didSet会监听插入值的时间而不是类层次结构?有没有办法让值听取层次结构?

1 个答案:

答案 0 :(得分:1)

问题是setMe被定义为隐式展开的可选项,如果在control的属性观察者中将值分配给setMe之前设置setMePleasesetMe的值将为nil,导致因展开力而导致崩溃。

如果setMe值实际上有意义或者提供默认值,则应将nil声明为简单的可选项。

class A: UIView{
    var setMe: Int?
    @IBInspectable var setMePlease: Int = 0{
        didSet{
            setMe = setMePlease
        }
    }
}

class B: A{
    @IBInspectable var control: Bool = false{
        didSet{
            if let setValue = setMe {
                let a = setMe + 1
            } else {
                let a = 1
            }

        }
    }
}

在初始化期间分配默认值时不会调用属性观察者,因此setMenil的属性观察者访问时controlclass Parent{ var aCopy:Int? var a = 1 { didSet{ aCopy = a } } } class Child: Parent { var b = 0{ didSet{ a = 2 let c = (aCopy ?? 0) + b } } } let child = Child() child.aCopy //nil child.a //1 child.b = 1 //b is assigned a new value, so its property observer is called child.a //2 child.aCopy //2

使用以下代码可以很容易地看到这种现象,即属性观察者仅在以编程方式更改变量值后调用,在为其分配默认值时不会调用它:

def invoice
  @order = current_user.orders.with_uuid(params[:id])
  if @order
    @order.order_attachment.with_document_file do |file|
      File.open(file.path, 'r') do |f|
        send_data f.read, :filename => 'report.pdf',
                          :type => 'application/pdf',
                          :disposition => 'attachment'
      end
    end
  else
    render nothing: true, status: :not_found
  end
end