美文网首页
OC 之 Property

OC 之 Property

作者: 张_何 | 来源:发表于2019-12-11 17:34 被阅读0次

介绍

  • 简介:属性(property)是Objective-C的一项特性,用于封装对象中的数据。这一特性可以令编译器自动编写与属性相关的存取方法,并且保存为各种实例变量。
  • 本质:属性的本质是实例变量与存取方法的结合。@property = ivar + getter + setter

特质

原子性相关

atomic
  • property 默认是atomic的
  • atomic 会保证了对象的原子操作,即atomic会对对象的setter、getter方法加一个锁来保证读写的原子操作;所谓原子操作就是不可分割的操作,在原子操作执行完毕之前,不会被任何其他任务或事件中断。但是atomic并不是线程安全的,如果线程 A 调了 getter,与此同时线程 B 、线程 C 都调了 setter——那最后线程 A get 到的值,有3种可能:可能是 B、C set 之前原始的值,也可能是 B set 的值,也可能是 C set 的值。同时,最终这个属性的值,可能是 B set 的值,也有可能是 C set 的值。所以atomic并不能保证对象的线程安全。
  • atomic 消耗性能,访问速度不快,因为要保证操作的整体完整
  • 保证CPU能在别的线程来访问这个属性之前,先执行完当前流程
- (void)setAtomicObj:(NSObject *)atomicObj{
    @synchronized(self) { // 同步锁
        if (_atomicObj != atomicObj) {
            [_atomicObj release];
            _atomicObj = [atomicObj retain];
        }
    }
}
- (NSObject *)atomicObj{
    @synchronized(self) {// 同步锁
        return _atomicObj;
    }
}
nonatomic
  • 非默认
  • 非原子操作,线程不安全
  • 访问速度快

内存管理相关

copy
  • block 和 字符串、集合中经常使用,这个可以看苹果的 Foundation 中的都是这样使用的
  • block 使用copy 是需要把存放在栈内存上的block copy到堆内存中去
  • 字符串和 集合使用copy,是因为他们都有mutable子类,当外界传一个可变的子类对象MA给当前属性时A,如果不用copy 的话用strong的话,外界可能会修改这个可变的子类对象MA,这个时候属性A也会发生变化,这样是比较危险的,比如内容一个collectionView执行刷的是后numberofRow返回的结果是10,但是执行到cellfForRowf方法是外部删除了MAde某些元素,这样会导致数组越界崩溃。如果使用copy的话,会重新copy一个新的对象出来,保证外面MA的改变不会波及到属性A
assign

Specifies that the setter uses simple assignment. This attribute is the default. You use this attribute for scalar types such as NSInteger and CGRect.

  • 对于基础数据类型property 默认是 assign
  • assign 可以用来修饰OC对象吗? 会有什么问题?
    assign 可以用来修饰oc对象,assign修饰oc对象会有野指针的问题。因为assign不会强引用对象,如果对象被释放而指针没有置为nil,依然指向该地址,下次访问该对象的时候就会造成野指针。基础数据类型由于是存放在栈内存上的,由系统分配和释放,所以不会有野指针的问题
  • assign 和 unsafe_unretain的区别?
    我猜想是这样的,assign 是直接赋值的,而unsafe_unretain是引用的,不知道是不是这样的,希望有人指点。
  • 使用 assign 修饰成员变量时帮我们生成的 set 方法是没有引用计数的处理的,使用 strong 时是有的
// 使用 strong 修饰时
-(void)setName:(NSString *) name {
    if(name != _name){
      [_name release];
      _name = [name retain];
    }
} 
// 使用 assign 修饰时
-(void)setName:(NSString *) name {
      _name = name;
} 

weak
  • weak 不会强引用对象,不会对当前对象的引用计数加1,当对象释放的时候指针自动置为nil
  • weak 可以用来修饰基础数据类型吗
    不可以,如果使用weak修饰基础数据类型xcode会报错
    @property (nonatomic, weak) NSInteger age; // Property with 'weak' attribute must be of object type
weak 的原理

1、当使用 weak 关键字初始化一个弱引用对象时,会调用id objc_initWeak(id *location, id newObj) 函数该函数内部调用static id storeWeak(id *location, objc_object *newObj) 函数,location代表weak 指针的地址,newObj 是被weak引用的对象。这个函数会根据对象的地址值获取 SideTables 中对应的 sideTable,更具获取的 sideTable 取出sideTable中的weak_table_t,weak_table_t 中存放着一个 weak_enter_t类型的hash 数组,然后会将对象和弱引用对象的地址包装成weak_enter_t类型的结构体,存放到weak_enter_t类型的hash 数组中,当弱引用的对象被释放时,dealloc ->_objc_rootDealloc-> object_dispose -> objc_destructInstance -> objc_clear_deallocating, 最后objc_clear_deallocating函数中会判断对象是否被弱引用过,如果是,就去 sideTable 中的 weak_table_t的 weak_entery_t 类型的列表中找对该对象对应的weak_entery_t然后将里面存放弱引用该对象的地址列表全部置为 nil, 然后将该weak_entery_t从 sideTable 中移除.

strong
  • 对于对象类型的 property默认是 strong
  • 强引用对象,会对当前对象的引用计数加1
  • strong 可以修饰基础数据类型吗?
    不可以,strong修饰基础数据类型xcode会报错@property (nonatomic, strong) NSInteger count; // Property with 'retain (or strong)' attribute must be of object type
unsafe_unretained
  • 弱引用对象,跟weak区别在于,对象被释放后weak会置为nil,unsafe_unretained不会,所以会有空指针的问题
  • unsafe_unretained 可以用来修饰oc对象,也可以修饰基础数据类型(通常不这么做)
@property (nonatomic, unsafe_unretained) NSInteger count;
@property (nonatomic, unsafe_unretained) NSString *home;

读写相关

  • 读写权限不写时默认为 readwrite 。一般可在 .h 里写成readonly,只对外提供读取,在 .m 的Extension中再设置为 readwrite 可进行写入。
  • readwrite
  • readonly

方法名

  • 用来指定存取方法的名称
  • getter
  • setter

值相关

  • nonnull
  • nullable

延伸

  • @dynamic:告诉编译器不要自动创建实现属性所用的实例变量,也不要为其创建存取方法。即使编译器发现没有定义存取方法也不会报错,运行期会导致崩溃。
  • @synthesize:在类的实现文件里可以通过 @synthesize 指定实例变量的名称。

类属性

  • 今天看UIDevice的API突然发现 OC中还有类属性,原来为了配合 swift3 的类属性,OC 也新增了类属性。其本质是为类生成了 set 和 get 方法,但没有生成成员变量,我们可在.m 中声明一个 static 变量来保存值,以便在 set 和 get 中使用
    参考链接
    @interface UIDevice : NSObject
    @property(class, nonatomic, readonly) UIDevice *currentDevice;

相关文章

  • OC 之 Property

    property 的本质: @property = ivar + getter + setter; 原子性相关 a...

  • OC @property

    @property(属性) 属性是对成员变量setter和getter的封装。 特性关键字 1. 原子性 atom...

  • OC - property

    @property变量 1.@property定义的变量,默认的修饰符是什么? 关于ARC下,不显示指定属性关键字...

  • OC -- @property

    建立一个Person类 @interface --> @end ==> .h中类的声明@implementatio...

  • OC Property

    1、四种写法的区别: PS:注意以下两点: 1>修饰属性问题,小心闪退: 上面的代码会闪退的。相当于以下代码。 正...

  • 52个有效方法(6) - 理解“属性”这一概念

    “属性”(property)是OC的一项特性,用于封装对象中的数据。 @property @Property是声明...

  • @property参数

    ARC 1>OC对象类型 @property(nonatomic,strong)类名 *属性名 @property...

  • iOS 成员变量、实例变量、property的区别和联系

    在iOS的第一个版本时,property是OC语言的一项新特性,在声明property之前必须首先声明与之对应的成...

  • iOS属性

    什么是属性 属性是OC语言中的一个机制,我们在OC中用@property来声明一个属性,其实@property是一...

  • iOS基础之Objective-C(一)

    OC面向对象新增语法:1、属性生成器: @property //声明属性例:@property (nonatomi...

网友评论

      本文标题:OC 之 Property

      本文链接:https://www.haomeiwen.com/subject/muiogctx.html