简体   繁体   中英

About copy property in Objective-C

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM