我试图在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 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;
}
}
但这很痛苦,因为访问器不是自动合成的,我必须手动编写它们。而且令人困惑,因为我现在可以使用_name
,name
,self._name
和self.name
。
现在,Stack Overflow上的大多数答案都表明我写了这个:
class Person2 {
var name: String? {
didSet {
self.name = self.name?.capitalizedString
}
}
}
但我认为这是令人困惑的,也不清楚我的意图。在设置名称属性之后,我没有尝试执行某些级联变异 ,我试图改变之前传递给setter 的值设置值。而且,我希望能够私下绕过这个设置器,而这种方法是不可能的。
为什么我不能写这个:
class Person3 {
var name: String? {
set (newName) {
name = newName?.capitalizedString
}
}
}
// This one actually makes the compiler crash on Xcode 7.2
或者这个:
class Person4 {
var name: String?
override func setName(newName) {
name = newName?.capitalizedString
}
}
甚至是这样:
class Person5 {
var name: String? {
willSet(newName) {
return newName?.capitalizedString
}
}
}
我是否遗漏了某些东西,或者只是没有办法让Objective-C拥有相同的构造?