NSString copy or strong?

结论

  • 对于copy修饰的属性来说,若赋值源是NSString、NSArray、NSURLRequest三者其中之一,复制时是shallow copy(浅复制),即地址相同,类型相同。
  • 一般情况下,NSString使用copy修饰。即:
@property (nonatomic, copy) NSString *string;

解释说明

结论1

首先,需要知道

copy和strong对应的所有权修饰符都是 __strong。
strong修饰的属性,赋值后,地址相同,类型相同。
copy修饰的属性,赋值时,通过 NSCopying 接口的 copyWithZone: 方法复制赋值源所生成的对象,赋值后,地址不一定相同,类型不一定相同。

而复制分为shallow copy与deep copy,区别如下:

shallow copy 即浅复制,没有产生新对象,指针指向原来对象。
deep copy 即深复制,产生新对象。

接着,Show the code

String相关属性

@property (nonatomic, strong) NSString *strongString;               /**

对String的测试

- (void)stringTest {
    //来源是NSString
    NSString *string = @"string";
    NSLog(@"address: %p | class: %@ of string",string,[string class]);
    self.strongString = string;
    self.cString = string;
    self.mStrongString = string;
    self.mCopyString = string;
    [self printStringInfo];

    NSLog(@"\n");

    //来源是NSMutableString
    NSMutableString *mutableString = [NSMutableString stringWithString:@"mutable string"];
    NSLog(@"address: %p | class: %@ of mutable string",mutableString,[mutableString class]);
    self.strongString = mutableString;
    self.cString = mutableString;
    self.mStrongString = mutableString;
    self.mCopyString = mutableString;
    [self printStringInfo];
}

- (void)printStringInfo {
    NSLog(@"address: %p | class: %@ of strong string",self.strongString,[self.strongString class]);
    NSLog(@"address: %p | class: %@ of copy string",self.cString,[self.cString class]);
    NSLog(@"address: %p | class: %@ of strong mutable string",self.mStrongString,[self.mStrongString class]);
    NSLog(@"address: %p | class: %@ of copy mutable string",self.mCopyString,[self.mCopyString class]);
}

(注:以上是只有部分代码,想了解更多,请查看文章底部的源代码)

然后,分别打印来源是NSString、NSArray、NSURLRequest的运行结果:

来源是NSString
来源是NSArray

来源是NSURLRequest

对比以上3张图中的地址及类型,可知:
来源是NSString、NSArray、NSURLRequest三者之一的,使用strong或copy修饰的,赋值结果都是一样的,可证明结论1:
对于copy修饰的属性来说,若赋值源是NSString、NSArray、NSURLRequest三者其中之一,复制时是shadow copy(浅复制),即地址相同,类型相同。

结论2

分别打印来源是NSMutableString、NSMutableArray、NSMutableNSURLRequest的结果:


来源是NSMutableString
来源是NSMutableArray
来源是NSMutableNSURLRequest

对比以上3张图中的地址及类型,可知:
来源若是NSMutableString,NSMutableArray,NSMutableURLRequest之一

  • 使用strong修饰的,赋值后,地址相同,类型也相同。
  • 使用copy修饰的,会复制赋值源所生成的对象,复制后,地址不同,而来源是NSMutableArray的,甚至连类型也不同(__NSArrayI__NSArrayM),说明复制时都是deep copy(深复制)。

(据了解,copy除了复制NSString、NSArray、NSURLRequest外,其他都是deep copy。)(未知真实性)

也就是说:
如果来源是NSString,使用copy或strong没有区别。
如果来源是NSMutableString,NSString对象会因其改变而改变。若使用copy,因为是深复制,产生了一个新的对象,就可以避免以上情况。

而一般使用NSString变量时,并不希望它可变,Objective-C的类型确定又是在运行时才决定的,那么赋值时,很可能会搞错赋值源的类型:NSMutableString误当作NSString,这样也许会带来不可预知的问题,而且此类问题一般不易察觉,所以可说明结论2:
一般情况下,NSString使用copy修饰。
当然,具体情况,具体分析,使用strong也无可厚非。

附录:剩余的主要代码

Array相关属性

@property (nonatomic, strong) NSArray *strongArray;                 /**

URL Request相关属性

@property (nonatomic, strong) NSURLRequest *strongRequest;          /**

对Array的测试

- (void)arrayTest {
    //来源是NSArray
    NSArray *array = @[ @"item1",@"item2"];
    NSLog(@"address: %p | class: %@ of array",array,[array class]);
    self.strongArray = array;
    self.cArray = array;
    self.mStrongArray = array;
    self.mCopyArray = array;
    [self printArrayInfo];
    
    NSLog(@"\n");
    
    //来源是NSMutableArray
    NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];
    NSLog(@"address: %p | class: %@ of mutable array",mutableArray,[mutableArray class]);
    self.strongArray = mutableArray;
    self.cArray = mutableArray;
    self.mStrongArray = mutableArray;
    self.mCopyArray = mutableArray;
    [self printArrayInfo];
}

- (void)printArrayInfo {
    NSLog(@"address: %p | class: %@ of strong array",self.strongArray,[self.strongArray class]);
    NSLog(@"address: %p | class: %@ of copy array",self.cArray,[self.cArray class]);
    NSLog(@"address: %p | class: %@ of strong mutable array",self.mStrongArray,[self.mStrongArray class]);
    NSLog(@"address: %p | class: %@ of copy mutable array",self.mCopyArray,[self.mCopyArray class]);
}

对URL Request的测试

- (void)urlRequestTest {
    //来源是NSURLRequest
    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    
    NSLog(@"address: %p | class: %@ of url request",urlRequest,[urlRequest class]);
    self.strongRequest = urlRequest;
    self.cRequest = urlRequest;
    self.mStrongRequest = urlRequest;
    self.mCopyRequest = urlRequest;
    [self printRequestInfo];
    
    NSLog(@"\n");
    
    //来源是NSMutableURLRequest
    NSMutableURLRequest *mutableURLRequest = [NSMutableURLRequest requestWithURL:url];
    NSLog(@"address: %p | class: %@ of mutable request",mutableURLRequest,[mutableURLRequest class]);
    self.strongRequest = mutableURLRequest;
    self.cRequest = mutableURLRequest;
    self.mStrongRequest = mutableURLRequest;
    self.mCopyRequest = mutableURLRequest;
    [self printRequestInfo];
}

- (void)printRequestInfo {
    NSLog(@"address: %p | class: %@ of strong request",self.strongRequest,[self.strongRequest class]);
    NSLog(@"address: %p | class: %@ of copy request",self.cRequest,[self.cRequest class]);
    NSLog(@"address: %p | class: %@ of strong mutable equest",self.mStrongRequest,[self.mStrongRequest class]);
    NSLog(@"address: %p | class: %@ of copy mutable request",self.mCopyRequest,[self.mCopyRequest class]);
}

你可能感兴趣的:(NSString copy or strong?)