当前位置:网站首页>[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是不可修改的数据了
边栏推荐
- Purpose of computer F1-F12
- The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
- 【嵌入式】Cortex M4F DSP库
- [sword finger offer] serialized binary tree
- The problem and possible causes of the robot's instantaneous return to the origin of the world coordinate during rviz simulation
- hutool优雅解析URL链接并获取参数
- LeetCode:387. 字符串中的第一个唯一字符
- LeetCode:26. 删除有序数组中的重复项
- Mongodb installation and basic operation
- LeetCode:剑指 Offer 48. 最长不含重复字符的子字符串
猜你喜欢
LeetCode:221. 最大正方形
Marathon envs project environment configuration (strengthen learning and imitate reference actions)
可变长参数
UML圖記憶技巧
swagger设置字段required必填
Using pkgbuild:: find in R language_ Rtools check whether rtools is available and use sys The which function checks whether make exists, installs it if not, and binds R and rtools with the writelines
Export IEEE document format using latex
UML图记忆技巧
Double pointeur en langage C - - modèle classique
After PCD is converted to ply, it cannot be opened in meshlab, prompting error details: ignored EOF
随机推荐
The mysqlbinlog command uses
个人电脑好用必备软件(使用过)
【剑指offer】序列化二叉树
Super efficient! The secret of swagger Yapi
【嵌入式】使用JLINK RTT打印log
C語言雙指針——經典題型
电脑F1-F12用途
704 binary search
Delay initialization and sealing classes
How to effectively conduct automated testing?
LeetCode:221. 最大正方形
TP-LINK 企业路由器 PPTP 配置
LeetCode:214. 最短回文串
Charging interface docking tutorial of enterprise and micro service provider platform
深度剖析C语言数据在内存中的存储
LeetCode:劍指 Offer 42. 連續子數組的最大和
C language double pointer -- classic question type
R language ggplot2 visualization, custom ggplot2 visualization image legend background color of legend
UnsupportedOperationException异常
Screenshot in win10 system, win+prtsc save location