Reputation: 121
I tested this sample code.
Sample.h
{
NSString *string1;
NSString *string2;
NSMutableString *string3;
}
@property (assign) IBOutlet NSWindow *window;
@property (strong,nonatomic) NSString *string1;
@property (copy,nonatomic) NSString *string2;
@property (strong,nonatomic) NSMutableString *string3;
@end
Sample.m
#import "Sample.h"
@synthesize string1;
@synthesize string2;
@synthesize string3;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
string1 = [[NSString alloc] init];
string2 = [[NSString alloc] init];
string3 = [[NSMutableString alloc] initWithString:@"test"];
string2 = string3;
string1 = string3;
[string3 appendString:@"test"];
NSLog(@"%@",string1);
NSLog(@"%@",string2);
NSLog(@"%@",string3);
}
@end
The result is
2012-09-23 00:11:48.610 sample[13468:303] testtest
2012-09-23 00:11:48.611 sample[13468:303] testtest
2012-09-23 00:11:48.611 sample[13468:303] testtest
I think string2 should be "test" because the property is copy. But string2 is "testtest".
string2 = [string3 copy];
This is the result I think.
string2 is "test"
Why? Please tell me, I can't sleep well.
Upvotes: 0
Views: 396
Reputation:
The problem is that you're not accessing the properties but you're immediately manipulating the backing instance variables. For those ivars, the =
operator is not special and does not have the effect of invoking the setter method, it's just a regular pointer assignment. So when you write
string2 = string3;
string1 = string3
then you assign the pointer to string3
to both string1
and string2
- whatever you do with string3
, it will be effective on the two other variables as well, because really, they point to the very same string instance.
What you have to do is one, declare your properties as copy
instead of strong
, two, write
self.string2 = string3;
self.string1 = string3
in order to invoke the setter methods and actually make independent copies of the strings.
P. s. By creating two empty instances of NSString using your
string1 = [[NSString alloc] init];
string2 = [[NSString alloc] init];
code and then reassigning something else to those variables, you're leaking memory.
Edit: you're lucky and you don't - by using ARC. With the old runtime, you would have wasted valuable bytes of your user's RAM.
But still. You don't need to create those instances - you're not directly memcpy()
'ing the characters into preallocated memory. Please read a comprehensive tutorial on C pointers before diving deep into iOS development.
Upvotes: 5
Reputation: 9185
I'm not sure why you say the setter semantics on the string2
property is copy
. You declared it strong
.
You set the NSString
pointer string2 to the NSMutableString
pointer string3. Then you proceeded to modify the mutable string pointed to by string3. So you should expect string2 to reflect that.
This is, by the way, the primary reason why you should use copy
setter semantics on objects that have mutable counterparts.
Upvotes: 0