美文网首页
细说@property(四)

细说@property(四)

作者: Chen_JF | 来源:发表于2019-01-31 17:52 被阅读0次

copy和strong

copy和strong的区别是面试中出现频率最高的,我们一般都知道,不可变对象属性修饰符使用copy,可变对象属性修饰符使用strong。

可变对象和不可变对象

  • Objective-C中存在可变对象和不可变对象的概念。像NSArray、NSDictionary、NSString这些都是不可变对象,像NSMutableArray、NSMutableDictionary、NSMutableString这些是可变对象。可变对象和不可变对象的区别是,不可变对象的值一旦确定就不能再修改。
- (void)testNotChange
{
    NSString *str = @"123";
    NSLog(@"str = %p",str);
    str = @"234";
    NSLog(@"after str = %p",str);

    NSMutableString *mutStr = [NSMutableString stringWithString:@"abc"];
    NSLog(@"mutStr = %p",mutStr);
    [mutStr appendString:@"def"];
    NSLog(@"after mutStr = %p",mutStr);
}

NSString是不可变对象,虽然在程序中修改了str的值,但是此处的修改实际上是系统重新分配了空间,定义了字符串,然后str重新指向了一个新的地址,这也是为何修改之后地址不一致的原因。而NSMutableString是可变对象,程序中改变了mutStr的值,且修改前后mutStr的地址一致

2019-01-31 18:02:41.350812+0800 TestClock[884:17969] str = 0x106ec1290
2019-01-31 18:02:41.350919+0800 TestClock[884:17969] after str = 0x106ec12d0
2019-01-31 18:02:41.457179+0800 TestClock[1000:21900] mutStr = 0x600002100540
2019-01-31 18:02:41.457261+0800 TestClock[1000:21900] after mutStr = 0x600002100540

不可变对象用strong会怎样?
上面说了,可变对象使用strong,不可变对象使用copy。那么,如果不可变对象使用strong来修饰,会有什么问题呢?

@property (nonatomic, strong) NSString *strongStr;

- (void)testStrongStr
{
    NSString *tempStr = @"123";
    NSMutableString *mutString = [NSMutableString stringWithString:tempStr];
    self.strongStr = mutString;  // 子类初始化父类
    NSLog(@"self str = %p  mutStr = %p",self.strongStr,mutString);   // 两者指向的地址是一样的
    [mutString insertString:@"456" atIndex:0];
    NSLog(@"self str = %@  mutStr = %@",self.strongStr,mutString);  // 两者的值都会改变,不可变对象的值被改变
}

首先明确一点,既然类型是NSString,那么则代表我们不希望testStr被改变,否则直接使用可变对象NSMutableString就可以了。另外需要提醒的一点是,NSMutableString是NSString的子类,对继承了解的应该都知道,子类是可以用来初始化父类的。

注意:我们定义的不可变对象strongStr,在开发者无感知的情况下被篡改了。所谓无感知,是因为开发者没有显示的修改strongStr的值,而是再修改其他变量的值时,strongStr被意外的改变。这显然不是我们想得到的,而且也是危险的。项目中出现类似的bug时,通常都很难定位。这就是不可变对象使用strong修饰所带来的风险。

可变对象用copy会怎样?
这里还是强调一下,既然属性类型是可变类型,说明我们期望再程序中能够改变mutString的值,否则直接使用NSString了。

@property (nonatomic, copy) NSMutableString *mutString;

- (void)testStrCopy
{
    NSString *str = @"123";
    self.mutString = [NSMutableString stringWithString:str];
    NSLog(@"str = %p self.mutString = %p",str,self.mutString); // 两者的地址不一样
    [self.mutString appendString:@"456"]; // 会崩溃,因为此时self.mutArray是NSString类型,是不可变对象
}

执行程序后,会崩溃,崩溃原因是:

[NSTaggedPointerString appendString:]: unrecognized selector sent to instance 0xed877425eeef9883

self.mutString没有appendString方法。self.mutString是NSMutableString类型,为何没有appendString方法呢?这就是使用copy造成的。错误原因就在下面这行代码

self.mutString = [NSMutableString stringWithString:str];

这行代码到底发生了什么。这行代码实际上完成了两件事:

// 首先声明一个临时变量
NSMutableString *tempString = [NSMutableString stringWithString:str];
// 将该临时变量copy,赋值给self.mutString
self.mutString = [tempString copy];

注意,通过[tempString copy]得到的self.mutString是一个不可变对象,不可变对象自然没有appendString方法,这也是为何会崩溃的原因。

相关文章

  • 细说@property(四)

    copy和strong copy和strong的区别是面试中出现频率最高的,我们一般都知道,不可变对象属性修饰符使...

  • 细说@property(三)

    @property修饰符 定义一个属性时,nonatomic、copy、strong、assign等被称作是关键字...

  • 细说@property(一)

    @property是什么? @property = 实例变量 + get方法 + set方法 上面这段代码,可能初...

  • 细说@property(二)

    @property合成和重写 自动合成定义一个@property,在编译期间,编译器会生成实例变量、getter方...

  • 细说@property(五)

    copy和mutableCopy copy和mutableCopy之间的差异主要和深拷贝和浅拷贝有关,先看一下深拷...

  • OC基础

    关于@property (1) @property的本质是啥编译器都帮你做了什么事儿详细说明(2) 关键字assi...

  • 面试题汇总

    ? 1. 基础 细说@property iOS基础面试题1(5.16) iOS基础面试题2 (5.24) 标哥(黄...

  • 18.@property中有哪些属性关键字?/ @propert

    @property中有哪些属性关键字?/ @property 后面可以有哪些修饰符? 属性可以拥有的特质分为四类:...

  • JavaScript(四):简述property

    要讲清楚JavaScript,首先需要明确以下几个知识点: Function也是对象,Function的proto...

  • npm ERR 常见错误整理

    npm ERR! Cannot read property 'match' of undefined 错误处理 四...

网友评论

      本文标题:细说@property(四)

      本文链接:https://www.haomeiwen.com/subject/ntbmdqtx.html