如何在不触发didSet观察者的情况下在Swift类的内部方法中设置属性?

时间:2015-10-24 02:53:03

标签: swift

在Objective-C中:

@interface User : NSObject
@property (nonatomic, strong) NSString  *name;

- (void)setName:(NString *newName) {
    _name = newName
    NSLog("newName = %@", newName);
}

User *user = [[User alloc] init];
user.name = @"Test"; // Call setName method and log "newName = Test"

但是在User类的内部方法中:

_name = "Test"; // Don't call setName

在斯威夫特:

class User : NSObject
var name: String {
    didSet {
        print("newName = " + name)
    }
}

如何在不触发didSet观察者的情况下在User类的内部方法中设置名称?与Objective-C中的_name = @"Test"一样?

2 个答案:

答案 0 :(得分:5)

您无法阻止调用didSet。但是,如果您希望由于某种原因重新创建直接在Objective-C中调用实例变量的机制,避免使用setter,则可以使用计算/存储的属性对。

例如:

class User {
    private var _name: String = ""

    var name: String {
        get {
            return _name
        }
        set {
            // any willSet logic
            _name = newValue
            // any didSet logic
        }
    }
}

从本质上讲,这实际上与您在创建属性时实际在Objective-C中获得的内容大致完全相同。

答案 1 :(得分:0)

来自the Swift docs

  

Swift属性没有相应的实例变量,并且不会直接访问属性的后备存储。这种方法避免了在不同的上下文中如何访问值的混淆,并将属性的声明简化为单一的,明确的声明。

  

只要为属性分配了新值,就会调用totalSteps的willSet和didSet观察者。即使新值与当前值相同,也是如此。

没有完全类比支持集成到Swift中的变量。您可以复制Objective-C属性(请参阅nhgrif的回答)。但是,这种方法在Swift中是陌生的,未来的程序员可能很难理解。如果您不想这样做,可以将didSet代码移到单独的函数中......

class User : NSObject {
    var name: String = ""

    func setNameAndPrint(name newName : String) {
        name = newName
        print("newName = " + name)

    }
}

let user = User()

user.name = "Aaron" // doesn't print anything
user.setNameAndPrint(name: "Zhao Wei") // prints "newName = Zhao Wei"

...或者你可以编写更明确的代码来模仿这种行为......

class User : NSObject {
    var printNameAfterSetting = true

    var name: String = "" {
        didSet {
            if printNameAfterSetting {
                print("newName = " + name)
            } else {
                printNameAfterSetting = true
            }
        }
    }
}

let user = User()

user.printNameAfterSetting = false
user.name = "Aaron" // prints nothing
user.name = "Zhao Wei" //prints "newName = Zhao Wei"

此示例使用bool,但您可以使用枚举或其他类型来表示更复杂的逻辑,具体取决于您的用例。