当前位置:网站首页>[OC-Foundation框架]--<Copy对象复制>
[OC-Foundation框架]--<Copy对象复制>
2022-07-06 08:50:00 【关于小司】
文章目录
copy 与 mutableCopy 方法
copy方法
copy 方法用于复制对象的副本,copy方法总返回对象的不可修改副本,即使该对象本身是可修改的
- 例如 :NSMutableString 的copy方法 返回不可修改的字符串对象
mutableCopy 方法
- mutableCopy 方法用于复制对象的可变副本,通常来说,mutableCopy 方法返回该对象可修改的副本,即使被复制的的对象是不可修改的
mutableCopy 方法 copy方法的共同特点
无论如何 copy 和 mutableCopy 返回的总是对象的副本,当程序对复制的副本进行修改时,原对象通常不会受到影响
mutableCopy和copy 程序实例
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableString *book = [NSMutableString stringWithString:@"疯狂iOS勒布朗"];
NSMutableString *bookCopy = [book mutableCopy];
[bookCopy replaceCharactersInRange:
NSMakeRange (2, 3)
withString:@"Android"];
NSLog(@"book 的值:%@", book);
// 字符串副本发生了改变
NSLog(@" bookCopy的值 为 %@", bookCopy);
NSString *str = @"fkiOS";
// 赋值str(不可变子串的副本 --可变)
NSMutableString * strCopy = [str mutableCopy];
//向可变后追加字符
[strCopy appendString:@" ,org"];
NSLog(@"%@ ", strCopy);
//调用book的Copy方法返回一个不可修改副本·
NSMutableString* bookCopy2 = [book copy];
// 不可修改发生错误
//Thread 1: "Attempt to mutate immutable object with appendString:"
//注释
// [bookCopy2 appendString:@"123456"];
}
return 0;
}`在这里插入代码片`
- 调用一个方法返回一个不可修改的副本时候
//调用book的Copy方法返回一个不可修改副本·
NSMutableString* bookCopy2 = [book copy];
// 不可修改发生错误
//Thread 1: "Attempt to mutate immutable object with appendString:"
//注释
// [bookCopy2 appendString:@"123456"];
- 在上面的程序中,虽然str是不可变字符串 但是通过mutableCopy 方法依然得到依然是可变副本,因此可以对strCopy进行修改
- 虽然book是可变字符串但是调用了copy的发哦的事不可变副本 因此对bookCopy2字符串进行修改 会导致错误
NScopying 与 NSmutableCopying 协议
通过copy 与 mutableCopy 方法复制对象的副本开起来很方便
但是自定义类是否可代用copy 与 mutableCopy 方法来复制副本吗?
OC规定
- Xcode的 报错可以看出 虽然NSObject提供了copy和 mutablecopy方法 但自定义类并不能调用这两个方法来复制自身
此细节不过多赘述
深复制和浅复制
浅复制
我们来看一个简单的对于类复制的例子
定义一个FKdog对象
注意在接口部分声明协议NSCopying
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface FKdog : NSObject <NSCopying> //声明copy协议 因为是一个类
@property (nonatomic, strong) NSMutableString* name;
@property (nonatomic, assign) int age;
@end
NS_ASSUME_NONNULL_END
浅复制的实现部分
- (id)copyWithZone:(nullable NSZone *)zone {
FKdog* dog = [[[self class] allocWithZone:zone] init];
dog.name = self.name; //注意区别
dog.age = self.age;
return dog;
}
#import <Foundation/Foundation.h>
#import "FKdog.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKdog *d1 = [[FKdog alloc] init];
d1.name = [NSMutableString stringWithString:@"旺财"];
d1.age = 20;
FKdog *d2 = [d1 copy];
[d2.name replaceCharactersInRange:NSMakeRange(0, 2) withString:@"旺财2号"];
NSLog(@"%@, %d", d1.name, d1.age);
NSLog(@"%@, %d", d2.name, d2.age);
}
return 0;
}
关于浅复制
上面调用了dog1 的copy方法复制了一个副本,并将副本复制dog2变量,接下来修改了dog2的name属性 输出
发现我们只是修改了dog2的name 但是为何dog1 也变化了
注意,name是一个指针类型的变量,该变量里存放的字符串的地址,并不是字符串本身,这样赋值的效果是dog的name 属性与被复制对象self的name属性指向同一个字符串 而age变量不困如何改变 dog1都不会变
(我们把dog2的年龄改为100 发现dog1 还是20)如下
2022-05-25 19:19:55.815766+0800 OC-copy[15837:2289009] 旺财2号, 20 2022-05-25 19:19:55.815971+0800 OC-copy[15837:2289009] 旺财2号, 100 Program ended with exit code: 0
我们可以得出结论 只要是浅复制 只要是指针类型的属性
改变任意一个都会改变另一个 的属性值
深复制
深复制则会采取与之不同的方式 神复制不仅会复制对象本身,还会递归复制每个指针类型的属性 直到两个对象没有任何的公共部分 将实现NSCopy协议的修改即可实现深复制
浅复制到深复制
#import "FKdog.h"
@implementation FKdog
- (id)copyWithZone:(nullable NSZone *)zone {
FKdog* dog = [[[self class] allocWithZone:zone] init];
dog.name = [self.name mutableCopy];
//修改如下在指针类型变量的self之加上
//mutableCopy
dog.age = self.age;
return dog;
}
@end
- 可以看到dog1 的指针类型name不改变
关于深复制
上面程序中并没有简单地将被复制对象的 name 属性值赋给新对象的 name 属性,而是先将原对象的 name 属性值复制了一份可变副本,再将该可变副本的值赋给新对象的name 属性。
这样就保证了原 FKDog 对象与新的 FKDog 对象之问没有任何共用的部分,这就实现了深复制。当 FKDog 实现了深复制之后,再次编译、运行上面的 程序,将可以看到两个FKDog 对象之问没有任何关联,当一个FKDog对象的name 属性值改变时,另一个 FKDog对象的 name 属性值不会受到任何影响
Foundation 框架中的类大部分都只实现了浅复制。
额外的知识增加了
对于我们的浅复制 协议实现代码
- (id)copyWithZone:(nullable NSZone *)zone {
FKdog* dog = [[[self class] allocWithZone:zone] init];
dog.name = self.name; //注意区别
dog.age = self.age;
return dog;
}
#import <Foundation/Foundation.h>
#import "FKdog.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKdog *d1 = [[FKdog alloc] init];
d1.name = [NSMutableString stringWithString:@"旺财"];
d1.age = 20;
FKdog *d2 = [d1 copy];
[d2.name replaceCharactersInRange:NSMakeRange(0, 2) withString:@"旺财2号"];
NSLog(@"%@, %d", d1.name, d1.age);
NSLog(@"%@, %d", d2.name, d2.age);
}
return 0;
}
注意我们在给dog2赋值的时候 用的是copy方法但是我们此时的copy并没有变成可变copy 为什么dog2的name还可以被 改变呢?
-因为 我们在写NSCopying协议的时候进行了直等于符号 相当于我们在内部重写了copy方法这样子copy方法就会改变了
如果把方法变成这样子
dog.name = [self.name copy]; //注意区别
那么系统就会提示 dog2是不可修改的数据了
边栏推荐
- Bitwise logical operator
- swagger设置字段required必填
- Introduction to the differences between compiler options of GCC dynamic library FPIC and FPIC
- 【剑指offer】序列化二叉树
- 有效提高软件产品质量,就找第三方软件测评机构
- win10系统中的截图,win+prtSc保存位置
- Image,cv2读取图片的numpy数组的转换和尺寸resize变化
- LeetCode:673. 最长递增子序列的个数
- After reading the programmer's story, I can't help covering my chest...
- LeetCode:214. 最短回文串
猜你喜欢
TP-LINK 企业路由器 PPTP 配置
MYSQL卸载方法与安装方法
Esp8266-rtos IOT development
Mobile phones and computers on the same LAN access each other, IIS settings
Nacos 的安装与服务的注册
Deep analysis of C language data storage in memory
vb. Net changes with the window, scales the size of the control and maintains its relative position
The harm of game unpacking and the importance of resource encryption
Promise 在uniapp的简单使用
C语言双指针——经典题型
随机推荐
Navicat premium create MySQL create stored procedure
LeetCode:836. 矩形重叠
Image,cv2读取图片的numpy数组的转换和尺寸resize变化
Roguelike game into crack the hardest hit areas, how to break the bureau?
优秀的软件测试人员,都具备这些能力
C language double pointer -- classic question type
LeetCode:498. 对角线遍历
The harm of game unpacking and the importance of resource encryption
LeetCode:剑指 Offer 48. 最长不含重复字符的子字符串
R language uses the principal function of psych package to perform principal component analysis on the specified data set. PCA performs data dimensionality reduction (input as correlation matrix), cus
Introduction to the differences between compiler options of GCC dynamic library FPIC and FPIC
LeetCode:剑指 Offer 03. 数组中重复的数字
visdom可视化实现与检查介绍
[Hacker News Weekly] data visualization artifact; Top 10 Web hacker technologies; Postman supports grpc
Variable length parameter
Visual implementation and inspection of visdom
可变长参数
pytorch查看张量占用内存大小
Indentation of tabs and spaces when writing programs for sublime text
Deep analysis of C language data storage in memory