NSString + Copy

  • 拷贝

  • 目的: 产生一个副本对象

  • 比如桌面上有一个文件夹iOS,iOS文件夹中有一个名字叫做 iOS底层笔记二.docx的文件 .

  • command + C, command + V . 会有一个 iOS底层笔记二的副本.docx 的文件。

  • 这两个文件,我可以任意改变其中的一个文件,另一个文件不会受到影响。

  • 特点:跟原对象互不影响

    • 修改原对象,不会影响副本对象
    • 修改副本对象,不会影响原对象
  • 有一个对象 Person *p,它里面有大于10个的属性

  • 需求1,

    • 创建一个新的对象 Person *p2, 它的属性跟 p对象的属性一模一样
    • 这个时候就可以用 copy。
    • 这种类似于 克隆技术

如何使用 copy ?

  • 系统中自带的类型 有 copy 功能 。如: NSString , NSArray, NSDictionary
NSString *str;
NSString *str2 = [str copy];
NSString *str2 = [str mutableCopy];

NSArray *arr;
NSArray *arr2 = [arr copy];

NSDictionary *dic;
NSDictionary *dic2 = [dic copy];

iOS 提供了2个拷贝方法

copy:

  • 不可变拷贝,产生不可变副本

mutableCopy:

  • 可变拷贝,产生可变副本
NSString *str1 = [NSString stringWithFormat:@"test"];
NSString * str2 = [str1 copy];
NSMutableString * str3 = [str1 mutableCopy];

//  copy 和  mutableCopy 都会产生副本

NSLog(@"%@, %@, %@",str1, str2, str3);
// 打印结果: test, test, test
  • 但是 str2 和 str3 的类型是不一样的。
  • copy 产生的是不可变副本,所以类型还是 NSString
    *mutableCopy 产生的是可变副本,所以类型是 NSMutableString.

如何证明 str3 是可变字符串(类型是 NSMutableString)

[str3 appendString: @"123"];
NSLog(@"%@",str3);
// 打印结果: test123

测试 str2 是不是 可变类型 ?

// 原本应该写为:NSString * str2 = [str1 copy];
NSmutableString *str2 = [str1 copy];
[str2 appendString: @"123"];
NSLog(@"%@",str3);
// 打印结果: 报错,因为 NSString 没有 appendString 方法。

那如果str1 在创建的时候就是 可变字符串呢

NSMuatbleString *str1  = [NSMuatbleString stringWithFormat:@"test"];
NSString * str2 = [str1 copy];
NSMuatbleString * str3 = [str1 mutableCopy];
  • 不管 str1 创建的时候是 可变类型还是不可变类型。在调用 copy 的时候,返回的类型都是不可变类型。调用 mutableCopy 的时候,返回的类型都是 可变类型。

oc 对象的内存管理

  • 在 iOS 中,使用 引用计数 来管理 OC 对象的内存
  • 一个新创建的OC 对象引用计数默认是1,当引用计数减为0,OC对象就会销毁,释放其占用的内存空间
  • 调用 retain 会让 OC 对象的引用计数 + 1 , 调用 release 会让 OC 对象的引用计数 -1.
  • 内存管理的经验总结
    • 当调用 alloc,new,copy,mutableCopy 方法返回了一个对象,在不需要这个对象时,要调用 release 或 autorelease来释放它。
    • 想拥有某个对象,就让它的引用计数 + 1, 不想在拥有某个对象,就让它的引用计数 -1。
  • 可以通过以下私有函数来查看自动释放池的情况
    • extern void _objc_autoreleasePoolPrint(void);

当调用 alloc,new,copy,mutableCopy 方法返回了一个对象,在不需要这个对象时,要调用 release 或 autorelease来释放它。

NSMuatbleString *str1  = [NSMuatbleString stringWithFormat:@"test"];
// 需要释放 str2
NSString * str2 = [str1 copy];
// 需要释放 str3
NSMuatbleString * str3 = [str1 mutableCopy];

mrc 的时候,需要 用下面的方式写代码,才没有内存泄露
在这里插入图片描述

NSString *str1 = [NSString stringWithFormat:@"text"];

  • 这种写法,不使用 release。

打印这三个变量的地址:
在这里插入图片描述
在这里插入图片描述

可以看到 str1 和 str2 的内存地址一样。str3 的内存地址不一样。

内存图:
在这里插入图片描述

为什么会 这样,因为 str1 和 str2 的都是不可变的。所以没有必要 在创建一个 test来浪费内存。

在不可变的情况下,使用 copy 相当于 retain。
也就是说 NSString * str2 = [str1 copy]; = NSString * str2 = [str1 retain];

NSString *Str1 = [[NSString alloc] initWithFormat:@"text"]; 打印 str1.retainCount, 结果是 -1.这是因为 str1 是 tagged pointer 。
解决办法: 把 test 变成很长很长的字符串。

堆地址:
在这里插入图片描述

tagged pointer
在这里插入图片描述


深拷贝和浅拷贝

  • 深拷贝:内容拷贝,产生新的对象
  • 浅拷贝:指针拷贝,没有产生新的对象。
    在这里插入图片描述

可变字符串 + copy + mutableCopy = ?

在这里插入图片描述

在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值