iOS知识点整理2--property属性
1 @property本质
- @property关键字是xcode编译器的一个编译特性,它帮我们做了很多事
//例如Person类下的 @property (nonatomic, copy) NSString *name;
// 编译器干的活
// .h中
@interface Person{
// 声明成员变量
@protected
NSString *_name;
}
// name的getter和setter方法的声明
- (NSString *)name;
- (void)setName:(NSString *)name;
@end// .m中
@implementation Person
// 实现getter和setter方法
- (NSString *)name{
return _name;
}
- (void)setName:(NSString *)name{
_name = [name ];
}
@end
- 补充:
@synthesize name = _name;
是配合@property使用的,意思是在.m文件中的_name是对应叫做name的property属性。当我们在.m文件中将setter和getter方法都重写的时候,需要加这个声明,否则_name在.m中是找不到的会报错。
- 更深层次的本质,就需要runtime的知识了,可以参考
- 1)关键字总结
- 主要分为4类,原子性、内存管理语义、读写权限、方法名
- 原子性:
atomic
、nonatomic
- 读写权限:
readwrite
、readonly
- 内存管理语义:
assign
、strong
、weak
、copy
- 方法名:
getter=
,setter=
- ARC环境下,不显示指定任何关键字的时候,对于基本数据类型默认关键字是atomic、readwrite、assign,而对于普通的OC对象默认是atomic、readwrite、strong
- 2)关键字之间的区分
- assign与weak
- assign主要用于基本数据类型、枚举、结构体等等,主要进行赋值,
- weak是对对象的弱引用,对于引用的对象,不会增加它的内存引用计数,主要用于防止循环引用; weak修饰的对象释放掉后,weak属性值会被置成nil,防止野指针。
- strong与copy
- strong:对于对象的强引用,会增加对象的内存引用计数
- copy:有的时候我们引用某个对象,但是并不希望这个对象的数据受外部的干扰,这个时候我们就需要使用copy了,就是创建一个对象的副本,当我们操作这个副本的时候不会影响原来的对象,同时原来的对象的改变,也不会影响到我们拥有的这个副本。copy有深复制和浅复制,深复制是创建出一个新的对象,浅复制是增加对原有对象的引用计数。
- assign与weak
- 【iOS知识点整理2--property属性】1) protocol和category中如何使用property
- protocol中使用property,主要是声明属性的getter和setter方法,使用这个的目的是希望遵守protocol协议的对象能实现该属性
- category中使用@porperty也只会生成属性的getter和setter方法的声明,如果我们真的需要给 category 增加属性的实现,需要借助于运行时的两个函数
objc_setAssociatedObject
,objc_getAssociatedObject
- 2)weak属性如何实现
- 要实现 weak 属性,首先要搞清楚 weak 属性的特点:
weak 此特质表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同 assign 类似, 然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。 - 那么 runtime 如何实现 weak 变量的自动置nil?
runtime 对注册的类, 会进行布局,对于 weak 对象会放入一个 hash 表中。 用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。
- 要实现 weak 属性,首先要搞清楚 weak 属性的特点:
- 自定义的类如何实现copy
- 需声明该类遵从 NSCopying 协议
- 实现 NSCopying 协议。该协议只有一个方法:
- (id)copyWithZone:(NSZone *)zone;
- (instancetype)initWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex { if(self = [super init]) { _name = [name copy]; _age = age; _sex = sex; _friends = [[NSMutableSet alloc] init]; } return self; }- (id)copyWithZone:(NSZone *)zone { CYLUser *copy = [[[self class] allocWithZone:zone] initWithName:_name age:_age sex:_sex]; copy->_friends = [_friends mutableCopy]; return copy; }
- 需声明该类遵从 NSCopying 协议
- copy属性的setter方法的重写
- release旧值,copy新值
- (void)setName:(NSString *)name { _name = [name copy]; }
- 非集合类与集合类的copy区别
- 在非集合类对象中:对 immutable 对象进行 copy 操作,是指针复制,mutableCopy 操作时内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
- 集合类对象的copy
主要是2个注意点,仅仅集合对象的拷贝,还是拷贝集合对象及其内部的元素
NSMutableArray *array = [NSMutableArray arrayWithObjects: [NSMutableString stringWithString:@"a"],@"b",@"c",nil]; // 仅仅复制集合,里面的元素不会改变 NSArray *copyArray = [array copy]; NSMutableArray *mCopyArray = [array mutableCopy]; // 深度复制,集合与里面的元素都会复制一份 NSDictionary shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:YES];
- 在非集合类对象中:对 immutable 对象进行 copy 操作,是指针复制,mutableCopy 操作时内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。用代码简单表示如下:
推荐阅读
- 20190302|20190302 复盘翻盘
- 2020-04-07vue中Axios的封装和API接口的管理
- 小学英语必考的10个知识点归纳,复习必备!
- iOS中的Block
- 【韩语学习】(韩语随堂笔记整理)
- 记录iOS生成分享图片的一些问题,根据UIView生成固定尺寸的分享图片
- 三国谋略22(找准你的定位)
- 2019-08-29|2019-08-29 iOS13适配那点事
- Hacking|Hacking with iOS: SwiftUI Edition - SnowSeeker 项目(一)
- iOS面试题--基础