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的知识了,可以参考
2 property属性的关键字(ARC环境下)
  • 1)关键字总结
    • 主要分为4类,原子性、内存管理语义、读写权限、方法名
    • 原子性:atomicnonatomic
    • 读写权限:readwritereadonly
    • 内存管理语义:assignstrongweakcopy
    • 方法名:getter=setter=
    • ARC环境下,不显示指定任何关键字的时候,对于基本数据类型默认关键字是atomic、readwrite、assign,而对于普通的OC对象默认是atomic、readwrite、strong
  • 2)关键字之间的区分
    • assign与weak
      • assign主要用于基本数据类型、枚举、结构体等等,主要进行赋值,
      • weak是对对象的弱引用,对于引用的对象,不会增加它的内存引用计数,主要用于防止循环引用; weak修饰的对象释放掉后,weak属性值会被置成nil,防止野指针。
    • strong与copy
      • strong:对于对象的强引用,会增加对象的内存引用计数
      • copy:有的时候我们引用某个对象,但是并不希望这个对象的数据受外部的干扰,这个时候我们就需要使用copy了,就是创建一个对象的副本,当我们操作这个副本的时候不会影响原来的对象,同时原来的对象的改变,也不会影响到我们拥有的这个副本。copy有深复制和浅复制,深复制是创建出一个新的对象,浅复制是增加对原有对象的引用计数。
3 property拓展
  • 【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。
-3)copy的拓展
  • 自定义的类如何实现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; }

  • 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];

参考文档https://www.zybuluo.com/MicroCai/note/50592

    推荐阅读