简体   繁体   English

在Swift中将一个默认属性值传递给另一个

[英]Passing one default property value to another in Swift

Imagine I want to do something like the following. 想象一下我想做以下事情。 I have a custom subclass of UIView, with several properties. 我有一个带有几个属性的UIView的自定义子类。 One of those properties I want to initialise from another prior property. 我想从另一个先前的属性中初始化其中一个属性。

class MyView :UIView {

    var driver = HumanDriver()

    var car = Car(driver: driver)
    var plane = Plane(driver: driver)
    var train = Train(driver: driver)
    var spaceship = Spaceship(driver: driver)

    override init() {
        super.init()
    }
    required init(coder aDecoder: NSCoder) {
        super.init(coder:aDecoder)
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
}

This code will present an error: 'MyView.Type' does not have a member named 'driver' . 此代码将显示错误: 'MyView.Type' does not have a member named 'driver' So one obvious attempt at fixing this would be to define the defaults in the initialiser. 因此,解决此问题的一个显而易见的尝试是在初始化程序中定义默认值。 This is fine if there is only ONE initialiser. 如果只有一个初始化程序,这很好。 But what if we have several? 但是,如果我们有几个呢? Well I can try to collect the common code in a single setup function, as below: 好吧,我可以尝试在单个设置功能中收集通用代码,如下所示:

class MyView :UIView {

    var driver = HumanDriver()

    var car
    var plane
    var train
    var spaceship

    override init() {
        setupMyView()
        super.init()
    }
    required init(coder aDecoder: NSCoder) {
        setupMyView()
        super.init(coder:aDecoder)
    }
    override init(frame: CGRect) {
        setupMyView()
        super.init(frame: frame)
    }

    func setupMyView() {
        car = Car(driver: driver)
        plane = Plane(driver: driver)
        train = Train(driver: driver)
        spaceship = Spaceship(driver: driver)
    }

}

But this also gives rise to an error, this time: 'self' used before super.init call . 但是,这也会引起错误,这一次: 'self' used before super.init call This is understandable since we are using self before init has been called. 这是可以理解的,因为在调用init之前我们正在使用self。

Is there any nice solution to this? 有什么好的解决方案吗? Obviously I could just used implicitly unwrapped optionals, but it seems like there should be a better way! 显然,我可以使用隐式解包的可选参数,但似乎应该有更好的方法!

How about overriding the driver setter and set the properties in there? 如何覆盖驱动程序设置程序并在其中设置属性? Something like this: 像这样:

class MyView :UIView {

    var driver:HumanDriver = HumanDriver() {
        didSet{
            car = Car(driver: driver)
            plane = Plane(driver: driver)
            train = Train(driver: driver)
            spaceship = Spaceship(driver: driver)
        }
    }

    var car: Car?
    var plane: Plane?
    var train: Train?
    var spaceship: Spaceship?
}

In this way you'll keep tidy your initializers. 这样,您将保持整洁的初始化程序。 Btw you'll have probably to add at least the required initializer but that's something else. 顺便说一句,您可能至少需要添加所需的初始化程序,但这就是其他内容。 I think this is one of the cleanest solution you might want to end up with. 我认为这是您可能想要得到的最干净的解决方案之一。

Hope this helps. 希望这可以帮助。

The answer here: https://stackoverflow.com/a/26772103/1025041 was really what I was looking for, although it really is a lot of boilerplate for what is trying to be achieved! 答案在这里: https : //stackoverflow.com/a/26772103/1025041确实是我在寻找的东西,尽管对于要实现的目标确实是很多样板! Lets hope Apple make this easier in future. 希望苹果公司在将来使此变得更容易。

For reference, this is how the method would apply to my example: 供参考,这是该方法适用于我的示例的方式:

extension UIView {
    enum InitMethod {
        case Default
        case Coder(NSCoder)
        case Frame(CGRect)
    }
}

class MyView: UIView {

    var driver = HumanDriver()

    var car
    var plane
    var train
    var spaceship

    override convenience init() {
        self.init(.Default)
    }

    override convenience init(frame: CGRect) {
        self.init(.Frame(frame))
    }

    required convenience init(coder aDecoder: NSCoder) {
        self.init(.Coder(aDecoder))
    }

    private init(_ initMethod: InitMethod) {

        car = Car(driver: driver)
        plane = Plane(driver: driver)
        train = Train(driver: driver)
        spaceship = Spaceship(driver: driver)

        switch initMethod {
            case .Default: super.init()
            case let .Coder(coder): super.init(coder: coder)
            case let .Frame(frame): super.init(frame: frame)
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM