在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"
一样?
答案 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)
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,但您可以使用枚举或其他类型来表示更复杂的逻辑,具体取决于您的用例。