我有三个NSString
属性声明如下:
@property(nonatomic,retain) NSString *currentPassword;
@property(nonatomic,retain) NSString *newPassword;
@property(nonatomic,retain) NSString *confirmPassword;
我用viewDidLoad
方法初始化它们:
currentPassword = [[NSString alloc]init];
newPassword = [[NSString alloc]init];
confirmPassword = [[NSString alloc]init];
有趣的是,在将它们初始化为不同的对象后,它们是同一个对象!
这是某种编译器优化吗?
谢谢
答案 0 :(得分:3)
这是某种编译器优化吗?
不完全。它是常量的特殊值,以及NSString
类实现的常见具体不可变类型/值的优化。
NSString
是不可变的。没有理由需要相同空字符串的多个实例。在这种简单的情况下,-[NSString init]
可以采用以下形式:
static NSString* const EmptyNSString = @"";
- (id)init
{
self = [super init];
[self release];
return EmptyNSString;
}
类似地,+ [NSString string]
:
+ (id)string
{
return EmptyNSString;
}
所以有一些静态不可变对象以这种方式使用它有意义。其他明显的例子包括+ [NSArray array]
和+ [NSNumber numberWithBool:]
。
这些常量中的每一个都可以表示在程序执行期间产生的许多数千个唯一分配。
这恰好起作用,因为NSString
作为类集群:返回一个实现由NSString
声明的接口的许多不透明类型之一的对象。因此,NSMutableString
类型可以适当地实现init
:
- (id)init
{
self = [super init];
if (nil != self) { ... }
return self;
}
最后,您几乎应该在所有情况下都将NSString
属性声明为copy
。
答案 1 :(得分:2)
由于NSString对象是不可变的(即在创建它们后无法更改)并且创建相同不可变字符串的几个不同实例没有任何意义,系统会尽可能地重用现有对象。
使用不带参数的构造函数可能就是一个例子。您还可以检查+stringWithString:
(和-initWithString:
)是否也返回(保留)参数字符串,copy
中的NSString
方法等同于retain
。< / p>
请记住,优化只有可能,因为我们知道NSString实例不会改变,而NSMutableString
的相同测试很可能会创建新的字符串实例。
P.S。关于NSAssert用法:
NSAssert 如果给定条件为假,则生成断言。
所以你的断言条件应该颠倒过来:
NSAssert(currentPassword && newPassword && confirmPassword,@"nil field");
答案 2 :(得分:0)
当您将NSString作为属性时,您应该指定属性“copy”。
答案 3 :(得分:0)
NSString被定义为不可变类型,因此只要编译器可以通过组合相同的字符串来优化事物,它就应该。如果您在代码中的两个不同位置使用@"myString"
,则它们将引用同一个对象。 @""
个字符串属于NSConstantString类