在Init函数之外初始化类属性

时间:2015-11-19 11:22:26

标签: ios swift

很抱歉,如果这是一个基本问题,但我无法在任何地方找到解决方案。我想在Init之外的函数中初始化类属性,并且只从构造函数内部调用它。我这样做是为了避免代码重复,因为当前版本看起来像这样:

public class WifiNameDisplay: UIView {
    var wifiImageView: UIImageView
    var networkName: UILabel
    public var networkSSID: String {
        didSet {
            networkName.text = networkSSID
            adjustSizeToContent()
        }
    }

    override public init(frame: CGRect) {
        networkSSID = "NETWORK"
        wifiImageView = UIImageView(image: UIImage(named: "wifi_icon.png")!)
        networkName = UILabel(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 400, height: wifiImageView.frame.size.height)))

        super.init(frame: frame)
    }


    convenience public init() {
        self.init(frame: CGRect.zero)
    }

    required public init(coder aDecoder: NSCoder) {
        networkSSID = "NETWORK"
        wifiImageView = UIImageView(image: UIImage(named: "wifi_icon.png")!)
        networkName = UILabel(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 400, height: wifiImageView.frame.size.height)))

        super.init(coder: aDecoder)!
    }
}

我想把它改成这样的东西:

public class WifiNameDisplay: UIView {
    var wifiImageView: UIImageView
    var networkName: UILabel
    public var networkSSID: String {
        didSet {
            networkName.text = networkSSID
            adjustSizeToContent()
        }
    }

    override public init(frame: CGRect) {
        initDefaultValues()
        super.init(frame: frame)
    }


    convenience public init() {
        self.init(frame: CGRect.zero)
    }

    required public init(coder aDecoder: NSCoder) {
        initDefaultValues()
        super.init(coder: aDecoder)!
    }

    func initDefaultValues() {
        networkSSID = "NETWORK"
        wifiImageView = UIImageView(image: UIImage(named: "wifi_icon.png")!)
        networkName = UILabel(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 400, height: wifiImageView.frame.size.height)))
    }
}

问题是编译器不允许这样做,在super.init初始化self之前调用“在方法调用'initDefaultValues'中使用'self'”。我想要的甚至可能,还是我被迫使用重复代码?

3 个答案:

答案 0 :(得分:1)

如果您将属性声明为隐式解包的选项,那么您可以在调用超类init函数后初始化它们 -

public class WifiNameDisplay: UIView {
    var wifiImageView: UIImageView!
    var networkName: UILabel!
    public var networkSSID: String! {
        didSet {
            networkName.text = networkSSID
          //  adjustSizeToContent()
        }
    }

    override public init(frame: CGRect) {

        super.init(frame: frame)
        initDefaultValues()
    }


    convenience public init() {
        self.init(frame: CGRect.zero)
    }

    required public init(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)!
        initDefaultValues()
    }

    func initDefaultValues() {
        networkSSID = "NETWORK"
        wifiImageView = UIImageView(image: UIImage(named: "wifi_icon.png")!)
        networkName = UILabel(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 400, height: wifiImageView.frame.size.height)))
    }
}

答案 1 :(得分:1)

据我所知,有两种方法。在定义值时初始化值:

public class WifiNameDisplay: UIView {
    var wifiImageView = UIImageView(image: UIImage(named: "wifi_icon.png")!)
    var networkName = UILabel(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 400, height: wifiImageView.frame.size.height)))
    public var networkSSID = "Network"
}

但这对您不起作用,因为networkName在此范围内不了解wifiImageView,因此无法为其找到正确的框架。我发现这对于设置偏移量,字符串常量等简单用例很有用,但是不建议将其用于UI元素。

其他方法是使变量(隐式解包)可选,并在initDefaultValues之后调用super.init

public class WifiNameDisplay: UIView {
    var wifiImageView: UIImageView!
    var networkName: UILabel!
    public var networkSSID: String! {
        didSet {
            networkName.text = networkSSID
        }
    }

    override public init(frame: CGRect) {
        super.init(frame: frame)
        initDefaultValues()
    }

    required public init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        initDefaultValues()
    }

    func initDefaultValues() {
        networkSSID = "NETWORK"
        wifiImageView = UIImageView(image: UIImage(named: "wifi_icon.png")!)
        networkName = UILabel(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 400, height: wifiImageView.frame.size.height)))
    }
}

答案 2 :(得分:0)

将要在init函数之外初始化的属性更改为lazy属性:

lazy var  networkName:UILabel = { return UILabel(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 400,     
                                  height: self. wifiImageView.frame.size.height)))}()