首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >是否可以允许在Swift中初始化期间调用didSet?

是否可以允许在Swift中初始化期间调用didSet?
EN

Stack Overflow用户
提问于 2014-08-11 00:38:57
回答 9查看 54.5K关注 0票数 250

问题

Apple's docs指定:

首次初始化属性时,不会调用

willSet和didSet观察器。只有在初始化上下文之外设置属性值时,才会调用它们。

是否可以在初始化过程中强制调用这些函数?

为什么?

假设我有这样一个类

代码语言:javascript
复制
class SomeClass {
    var someProperty: AnyObject {
        didSet {
            doStuff()
        }
    }

    init(someProperty: AnyObject) {
        self.someProperty = someProperty
        doStuff()
    }

    func doStuff() {
        // do stuff now that someProperty is set
    }
}

我创建了doStuff方法,以使处理调用更加简洁,但我宁愿只处理didSet函数中的属性。有没有办法在初始化过程中强制调用它?

更新

我决定只删除我的类的方便初始化器,并强制您在初始化后设置该属性。这让我知道didSet总是会被调用。我还没有决定总体上这样做是否更好,但它很适合我的情况。

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2014-08-11 01:10:44

创建自己的set-Method并在init-Method中使用它:

代码语言:javascript
复制
class SomeClass {
    var someProperty: AnyObject! {
        didSet {
            //do some Stuff
        }
    }

    init(someProperty: AnyObject) {
        setSomeProperty(someProperty)
    }

    func setSomeProperty(newValue:AnyObject) {
        self.someProperty = newValue
    }
}

通过将someProperty声明为

AnyObject! (一个隐式展开的可选类型),您可以在不设置someProperty的情况下允许self完全初始化。当您调用setSomeProperty(someProperty)时,您正在调用一个与self.setSomeProperty(someProperty)等效的函数。通常你不能这样做,因为self还没有完全初始化。由于someProperty不需要初始化,并且您正在调用依赖于self的方法,因此Swift离开初始化上下文,didSet将运行。

票数 118
EN

Stack Overflow用户

发布于 2015-11-29 13:54:22

如果您在初始化器中使用defer,用于更新任何已初始化的可选属性或进一步更新已初始化的非可选属性,并且在调用任何super.init()方法之后,将调用您的willSetdidSet等。我发现这比实现单独的方法更方便,你必须跟踪在正确的地方调用。

例如:

代码语言:javascript
复制
public class MyNewType: NSObject {

    public var myRequiredField:Int

    public var myOptionalField:Float? {
        willSet {
            if let newValue = newValue {
                print("I'm going to change to \(newValue)")
            }
        }
        didSet {
            if let myOptionalField = self.myOptionalField {
                print("Now I'm \(myOptionalField)")
            }
        }
    }

    override public init() {
        self.myRequiredField = 1

        super.init()

        // Non-defered
        self.myOptionalField = 6.28

        // Defered
        defer {
            self.myOptionalField = 3.14
        }
    }
}

将会产生:

代码语言:javascript
复制
I'm going to change to 3.14
Now I'm 3.14
票数 347
EN

Stack Overflow用户

发布于 2015-04-08 05:51:01

作为Oliver答案的一种变体,您可以将这些行包含在闭包中。例如:

代码语言:javascript
复制
class Classy {

    var foo: Int! { didSet { doStuff() } }

    init( foo: Int ) {
        // closure invokes didSet
        ({ self.foo = foo })()
    }

}

编辑: Brian Westphal的回答是更好的imho。他的好消息是它暗示了他的意图。

票数 82
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25230780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档