当前位置: 首页 > news >正文

【iOS】属性关键字

目录

深浅拷贝

自定义类

容器类深拷贝

属性关键字

原子操作

atomic

nonatomic

读写权限

readwrite

readonly

内存管理

weak

assign

strong

retian

copy

strong与copy

补充

属性关键字格式

ARC下@property的默认属性


深浅拷贝

关于深浅拷贝,笔者在之前已经有博客进行过详细的阐述,下面附上深浅拷贝的链接

深浅拷贝

在这篇博客中,笔者讲述了深浅拷贝的基本概念和区别,也解释了一些有关于容器类深拷贝的知识,这里来做一些补充。

自定义类

自定义类无论是copy还是mutablecopy都为深拷贝,因为自定义类没有copyWithZone:和mutableCopyWithZone:两个方法,需要遵守NSCopying和NSMutableCopying协议自己实现这两个拷贝方法。

容器类深拷贝

容器类对象的深拷贝分为两种,一种是单层深拷贝,另一种是完全深拷贝。

  • 单层深拷贝:对于副本对象本身是深拷贝,但是容器中的所有对象都是浅拷贝
  • 完全深拷贝:对于副本对象本身与其里面的所有对象都是深拷贝

非可变容器类在mutablecopy时是单层深拷贝,可变容器类在使用copy和mutablecopy时都是单层深拷贝,那么要如何才能实现容器类的完全深拷贝呢?

先给出结论:当容器类对象中的对象是自定义对象或不为immutable对象,使用initWithArray:copyItems:方法(第二个参数设置为YES)可以实现完全深拷贝;当容器内对象是容器类时,使用initWithArray:copyItems:方法(第二个参数设置为YES)可以实现单层浅拷贝,这时就需要使用归档和解档来实现完全深拷贝

比如:dataArray3 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:dataArray2]]

- (void)test {NSMutableArray* array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"1"],[NSMutableString stringWithString:@"2"],[NSMutableString stringWithString:@"3"],[NSMutableString stringWithString:@"4"],nil];NSMutableArray* array2 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"one"],[NSMutableString stringWithString:@"two"],[NSMutableString stringWithString:@"three"],[NSMutableString stringWithString:@"four"],array1,nil];NSMutableArray* array3 = [array2 mutableCopy];//NSMutableArray* array4 = [[NSMutableArray alloc] initWithArray:array2 copyItems:YES];NSMutableString* mutableString;mutableString = array2[0];[mutableString appendString:@"--ONE"];NSLog(@"array3:%@", array3);NSLog(@"array2:%@", array2);
}

这段代码容器类对象使用mutablecopy,输出的结果是修改array2中的元素,array3也会发生改变,说明这是单层深拷贝,也就是说对于array2和array3是深拷贝,而对于数组中的元素却还是浅拷贝。

如果使用initWithArray:copyItems:方法呢?

- (void)test {NSMutableArray* array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"1"],[NSMutableString stringWithString:@"2"],[NSMutableString stringWithString:@"3"],[NSMutableString stringWithString:@"4"],nil];NSMutableArray* array2 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"one"],[NSMutableString stringWithString:@"two"],[NSMutableString stringWithString:@"three"],[NSMutableString stringWithString:@"four"],array1,nil];NSMutableArray* array3 = [array2 mutableCopy];NSMutableArray* array4 = [[NSMutableArray alloc] initWithArray:array2 copyItems:YES];NSMutableString* mutableString;mutableString = array2[0];[mutableString appendString:@"--ONE"];NSLog(@"array3:%@", array3);NSLog(@"array2:%@", array2);NSLog(@"array4:%@", array4);
}

可以看出,array4实现了完全深拷贝。

那如果是针对于容器类里的容器类对象呢?

- (void)test {NSMutableArray* array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"1"],[NSMutableString stringWithString:@"2"],[NSMutableString stringWithString:@"3"],[NSMutableString stringWithString:@"4"],nil];NSMutableArray* array2 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"one"],[NSMutableString stringWithString:@"two"],[NSMutableString stringWithString:@"three"],[NSMutableString stringWithString:@"four"],array1,nil];NSMutableArray* array3 = [array2 mutableCopy];NSMutableArray* array4 = [[NSMutableArray alloc] initWithArray:array2 copyItems:YES];NSMutableString* mutableString;mutableString = array2[0];[mutableString appendString:@"--ONE"];NSMutableString* mutableString1;NSMutableArray* mutableArray = array2[4];mutableString1 = mutableArray[0];[mutableString1 appendString:@"--ONE"];NSLog(@"array3:%@", array3);NSLog(@"array2:%@", array2);NSLog(@"array4:%@", array4);
}

 

 可以看出容器类中的容器类对象使用initWithArray:copyItems:只能实现单层的深拷贝。

属性关键字

@property

@synthesize

@dynamic

这三个关键字是有关于属性自动合成存取方法的关键字:

用 @property 语法来声明属性。@property 会帮我们自动生成属性的 setter 和 getter 方法的声明

@synthesize帮我们自动生成 setter 和 getter 方法的实现以及合成实例变量。

@dynamic告诉编译器不用自动进行 @synthesize,你会在运行时再提供这些方法的实现,无需产生警告

现在的版本已经不再需要@synthesize 编译器会自动合成存取方法。

下面是一些修饰属性的关键字

原子操作

原子操作:属性是否有原子性可以理解为线程是否安全

  • atomic

原子性,加同步锁,默认修饰符。 使用atomic会损耗性能,也不一定保证线程安全。如果保证线程安全需要使用其他锁机制。

非原子性,不实用同步锁。 声明属性时基本设置为nonatomic。使用nonatomic能够提高访问性能。

读写权限

读写权限不写时默认为 readwrite

属性拥有setter方法和getter方法

仅有getter方法

内存管理

weak

  1. ARC 下才能使用;
  2. 修饰弱引用,不增加对象引用计数,主要可以用于避免循环引用;
  3. weak 修饰的对象在被释放之后,会自动将指针置为 nil,不会产生悬垂指针;

assign

  1. 既可以修饰基本数据类型,也可以修饰对象类型;
  2. setter 方法的实现是直接赋值,一般用于基本数据类型 
  3. 修饰对象类型时,不增加其引用计数;
  4. 会产生悬垂指针(悬垂指针:assign 修饰的对象在被释放之后,指针仍然指向原对象地址,该指针变为悬垂指针。这时候如果继续通过该指针访问原对象的话,就可能导致程序崩溃)。

strong

  1. ARC 下才能使用;
  2. 原理同 retain;
  3. 但是在修饰 block 时,strong 相当于 copy,而 retain 相当于 assign。

retian

  1. MRC 下使用,ARC 下基本使用 strong;
  2. 修饰强引用,保留新值,释放旧值,再设置新值,同时将新对象的引用计数加 1;
  3. setter 方法的实现是 release 旧值,retain 新值,用于 OC 对象类型。

copy

setter 方法的实现是 release 旧值,copy 新值。用于 NSString、NSArray、NSDictionary 是为了保证赋值后是一个不可变对象,以免遭外部修改而导致不可预期的结果。

strong与copy

如果属性声明中指定了copy特性,合成方法会使用类的copy方法

相同点:用于修饰标识拥有关系的对象

不同点:strong的赋值是多个指针指向同一个地址,而copy的复制就是每次会在内存中复制一份对象,指针指向不同的地址。

strong与copy可以理解为深浅拷贝的区别

补充

属性关键字格式

推荐按照下面的格式来定义属性

@property (nonatomic, readwrite, copy) NSString *name;

属性的修饰符应该按照上面的顺序排列:原子操作、读写权限、内存管理

ARC下@property的默认属性

对于基本数据类型:atomic、readwrite、assign
对于普通的Objective-C对象:atomic、readwrite、strong

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 爬取知乎回答
  • Unity(2022.3.41LTS) - 着色器
  • vulnhub靶场-DC2
  • 使用Blender云渲染的好处是什么?
  • 滚雪球学MyBatis-Plus(04):基础配置
  • 如何用Java SpringBoot打造助农捐赠平台?2025年25届毕业生必看+最新设计实现攻略!
  • Spring Cloud Gateway整合基于STOMP协议的WebSocket实战及遇到问题解决
  • Catia二次开发“CAAV5-ERROR: unauthorized API for CAA V5”错误
  • Docker 修改镜像源
  • 公司电脑的敏感文件怎么审查?分为六步,步步为营,保护文件不泄密
  • 联蔚盘云亮相CDIE消费品行业峰会
  • LABVIEW数据保存文件
  • springboot整合logback进行日志管理(下篇)
  • 连接型CRM+智能制造,助力医疗器械企业高质量发展
  • 搜维尔科技:数据手套+机械手遥操作,五指触感灵巧手解决方案!
  • CentOS从零开始部署Nodejs项目
  • CODING 缺陷管理功能正式开始公测
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • HTTP请求重发
  • Intervention/image 图片处理扩展包的安装和使用
  • java概述
  • MaxCompute访问TableStore(OTS) 数据
  • Odoo domain写法及运用
  • Python爬虫--- 1.3 BS4库的解析器
  • Sass Day-01
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 从0实现一个tiny react(三)生命周期
  • 爬虫模拟登陆 SegmentFault
  • 试着探索高并发下的系统架构面貌
  • 运行时添加log4j2的appender
  • 再谈express与koa的对比
  • - 转 Ext2.0 form使用实例
  • 2017年360最后一道编程题
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 湖北分布式智能数据采集方法有哪些?
  • 如何正确理解,内页权重高于首页?
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​MySQL主从复制一致性检测
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #在 README.md 中生成项目目录结构
  • (02)Unity使用在线AI大模型(调用Python)
  • (7)STL算法之交换赋值
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (第30天)二叉树阶段总结
  • (三十五)大数据实战——Superset可视化平台搭建
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)C#调用WebService 基础
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转)菜鸟学数据库(三)——存储过程
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .NET 通过系统影子账户实现权限维持
  • .net 验证控件和javaScript的冲突问题
  • /tmp目录下出现system-private文件夹解决方法