Objective c 在Swift中覆盖或绕过访问器
我试图在Swift中复制Objective-C的ivar/setter访问。 以下是在Objective-C中使用setter与ivar的简单示例:Objective c 在Swift中覆盖或绕过访问器,objective-c,swift,swift2,setter,getter-setter,Objective C,Swift,Swift2,Setter,Getter Setter,我试图在Swift中复制Objective-C的ivar/setter访问。 以下是在Objective-C中使用setter与ivar的简单示例: @interface Person : NSObject @property (nonatomic, strong) NSString *name; @end @implementation Person - (void)setName:(NSString *)name { // Let's assume that this is a
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@end
@implementation Person
- (void)setName:(NSString *)name {
// Let's assume that this is an expensive operation.
// I want to perform it only when necessary.
_name = name.capitalizedString;
}
- (void)someMutatingMethod1
{
Person *otherPerson = nil; // Get a person
NSString *newName = otherPerson.name;
// At this point, I know that newName is in the corect format because it comes from a Person object.
// I don't need the expensive setter work, so I bypass it with direct ivar access.
_name = newName;
}
- (void)someMutatingMethod2
{
NSString *userInputName = @"john";
// It's user input, I need the setter to perform it's work.
self.name = userInputName;
}
@end
在Swift中复制此类最接近的方法是:
class Person {
private var _name: String?
var name: String? {
get {
return _name
}
set (newName) {
_name = newName?.capitalizedString
}
}
func someMutatingMethod1() {
let otherPerson:Person? = nil;
_name = otherPerson?.name;
}
func someMutatingMethod2() {
let userInputName = "john";
self.name = userInputName;
}
}
但这很痛苦,因为访问器不是自动合成的,我必须手动编写它们。这让人困惑,因为我现在可以使用\u name
,name
,self.\u name
和self.name
现在,关于堆栈溢出的大多数答案都建议我这样写:
class Person2 {
var name: String? {
didSet {
self.name = self.name?.capitalizedString
}
}
}
但我认为这让人困惑,也不清楚我的意图。我不是在设置name属性后执行级联变异,而是在设置值之前变异传递给setter的值。再一次,我希望能够私下绕过这个setter,这是这种方法不可能做到的
为什么我不能这样写:
class Person2 {
var name: String? {
didSet {
self.name = self.name?.capitalizedString
}
}
}
class Person3{
变量名称:字符串{
集合(新名称){
name=newName?.capitalizedString
}
}
}
//这实际上使编译器在Xcode 7.2上崩溃。您使用\u name
的第一个实现是完全正确的,并且恰好与ObjC的工作方式完全匹配。它没有什么问题,代价可能是两行“不必要的”代码。正如您所注意到的,解决这个问题只会使事情变得更加复杂。它看起来是相同的,但工作原理不同,因为在这种情况下,name
和\u name
都是属性(为\u name
合成了默认访问器)。但是,也许在Swift中不存在ivar和属性之间的分离?我仍然认为,为了清晰起见,我将在任何地方都使用此实现,但我很惊讶,没有一种内置的方法可以做到这一点,而不编写与Objective-C类似的大量代码。您是对的,没有强大的ivar/属性类似于ObjC中的复制。在大多数情况下,这是一个好处。如果您经常这样做(将属性设置为非其实际值的内容),您应该询问您是否在做其他错误的事情。通常,在foo.x=y之后,foo.x应该返回y。如果不是,它就不是一个真正的“属性”,您可能应该编写一个显式的updateX()方法来明确这一点(并使setter私有),而不是重写setter。也就是说,ObjC在处理CoreData或锁定时一直都有这种重复。您通常必须维护“基本”访问器。(请参见primitiveValueForKey:)您使用\u name
的第一个实现是完全正确的,并且恰好与ObjC的工作方式完全匹配。它没有什么问题,代价可能是两行“不必要的”代码。正如您所注意到的,解决这个问题只会使事情变得更加复杂。它看起来是相同的,但工作原理不同,因为在这种情况下,name
和\u name
都是属性(为\u name
合成了默认访问器)。但是,也许在Swift中不存在ivar和属性之间的分离?我仍然认为,为了清晰起见,我将在任何地方都使用此实现,但我很惊讶,没有一种内置的方法可以做到这一点,而不编写与Objective-C类似的大量代码。您是对的,没有强大的ivar/属性类似于ObjC中的复制。在大多数情况下,这是一个好处。如果您经常这样做(将属性设置为非其实际值的内容),您应该询问您是否在做其他错误的事情。通常,在foo.x=y之后,foo.x应该返回y。如果不是,它就不是一个真正的“属性”,您可能应该编写一个显式的updateX()方法来明确这一点(并使setter私有),而不是重写setter。也就是说,ObjC在处理CoreData或锁定时一直都有这种重复。您通常必须维护“基本”访问器。(请参见primitiveValueForKey:)