美文网首页
iOS 属性

iOS 属性

作者: Fat_Blog | 来源:发表于2021-04-01 20:04 被阅读0次

    @property

    • property = ivar(变量) + set方法 + get方法

    我们每次在增加一个属性,系统都会在ivar_list 中添加一个成员变量的描述,在method_list中增加settergetter 方法的描述,在属性列表中增加一个属性的描述,然后计算该属性在对象中的偏移量,然后给出 settergetter方法对应的实现,在setter 方法中从偏移量的位置开始赋值,在 getter 方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转.

    @property (nonatomic, strong)UIView *bgView;
    

    当使用@property声明一个bgView的属性时,在编译阶段,编译器会自动给对象bgView添加一个实例变量_bgView以及它的set方法和get方法

    代码验证

    #import "ViewController.h"
    
    #include <objc/runtime.h>
    
    @interface ViewController ()
    
    @property (nonatomic, strong)UIView *bgview;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        unsigned int count = 0;
        Ivar *varList = class_copyIvarList([self class], &count);
        for (unsigned int i = 0; i < count; i++) {
            const char *varName = ivar_getName(varList[i]);
            printf("成员变量-------%s\n",varName);
        }
        
        Method *methodList = class_copyMethodList([self class], &count);
        for (unsigned int i = 0; i < count; i++) {
            SEL methodName = method_getName(methodList[i]);
            NSLog(@"方法-------%@",NSStringFromSelector(methodName));
        
        }
    }
    @end
    

    打印日志

    成员变量-------_bgview
    2021-03-31 19:19:40.612196+0800 basicLearn[12511:760231] 方法-------bgview
    2021-03-31 19:19:40.612294+0800 basicLearn[12511:760231] 方法-------setBgview:
    2021-03-31 19:19:40.612378+0800 basicLearn[12511:760231] 方法-------.cxx_destruct
    2021-03-31 19:19:40.612465+0800 basicLearn[12511:760231] 方法-------viewDidLoad

    • 如果我们想自定义属性的存取方法,那么需要注意以下几点
      1.同时自定义setget方法,会导致property失效
      image.png
      2.而如果我们重写了set方法,编译器会自动生成get方法,反过来重写了get方法,编译器也会自动生成set方法

    @synthesize

    • 当我们需要同时重写属性bgViewsetget方法时,可以用synthesize声明属性
    • 当我们用synthesize声明了属性,但是没有重写setget方法,编译器还是会自动补全存取方法的

    代码展示

    1.bgView是属性,而_bgView是成员变量
    2.@synthesize bgView = _bgView; 这个方法是告诉编译器bgView属性是_bgView实例变量生成settergetter方法的实现

    @interface ViewController ()
    
    @property (nonatomic, strong)UIView *bgView;
    
    @end
    
    @implementation ViewController
    
    @synthesize  bgView = _bgView;
    
    - (void)setBgView:(UIView *)bgView {
        _bgView = bgView;
    }
    - (UIView *)bgView {
        return _bgView;
    }
    

    @dynamic

    • @dynamic是告诉编译器 属性 的setter方法 和 getter方法 由用户自己实现
    • 但要注意的是 如果用@dynamic声明一个属性,但没有手动实现settergetter方法,编译时是不会有问题的,但代码运行时调用了属性的set方法或者get方法,程序就会崩溃
    • 还有一个应用:当有一个Father类,里面有一个str的属性,这时创建了一个Son类继承了Father类,在Son类里同时也声明一个str的属性,这时如果我们重写子类Son里的str属性,就会报错,因为我们同时在FatherSon类里声明了str属性,系统默认是会在父类Father里合成str的存取方法,这时我们就需要在子类Son类里用@dynamic修饰str,告诉编译器在子类里不用去合成str属性的存取方法

    读写权限 readonly readwrite

    • 如果在声明属性时,没有说明是readonly,那么默认都是readwrite
    • 如果属性被声明为readonly,那么我们获取调用该属性的get方法,调用set方法会报错
    @property (nonatomic, copy,readonly)NSString *str;
    

    readonly可以应用在 父类的.h文件将属性设置为readonly,在.m文件又设置为readwrite,那么继承该父类的子类只能获取这个属性而不能修改它的值,只有父类才有权利去修改这个属性的值

    原子性 nonatomic atomic

    • atomicnonatomic修饰属性时生成的settergetter方法是不一样的
      atomic修饰属性会在属性的存取方法里加上的同步锁🔒 @synchronized(self),同步锁()里的self可以被其他对象代替,内是根据括号内的内容来判断是否是同一个同步代码块,比如
      当两个并发线程访问同一个对象object中的这个synchronized(self)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
    • atomic里的set方法和get方法都加了同步锁🔒,这样可以保证 读写 功能的完成性,但是不能保证对象的线程安全,比如:线程B,C同时调用属性的set方法,线程A去调用get方法,那么get到的值有可能是B设置的,有可能是C设置的,也有可能是B,C之前设置的
    • nonatomic这个的setget方法没有加锁,因此不能保证setget操作的完成性,因此get出的属性可能刚被释放掉,也可能是不完整的,但是由于没有加锁,访问的速度会相对快,性能的消耗也相对少

    strong,weak,assign,retain,copy

    • strong

    strong 表示强引用,用于修饰NSObject对象,不能修饰基础数据类型,
    strong修饰的对象被引用时 引用计数会➕1,当该对象的引用计数为0时,该对象会被释放掉

    • weak

    weak 表示弱引用,用于修饰NSObject对象,不能修饰基础数据类型,主要用于避免循环引用,要注意的是:weak修饰的对象才被初始化之后是会释放掉的,对象释放之后所有指向它的指针都会自动置为nil,这样可以防止野指针的问题

    //bgView是weak修饰的
    //这样初始化之后bgView就会被释放掉
    self.bgView = [[UIView alloc]init];
    
    • assign

    assign 可以同时用来修饰基础数据类型(CGFloat等)和对象,当用assign修饰对象时,作用和weak相似,但是对象被释放之后,不会自动将属性置为nil,那么容易出现野指针的问题

    • copy

    copy 作用类似与strong,修饰NSObject对象,不能修饰基础数据类型,当copy修饰的属性是可变时(NSMutable),copy后的对象,会变成不可变对象,(比如从NSMutableArray变成NSArray,那么调用增删操作时会引发crash,因为尽量不要用copy修饰可变对象),指针地址跟之前是不一样的,也就是说会重新分配一块新的内存空间

    • retain

    一般用于MRC模式下,修饰对象引用计数会加1,后来在ARC模式下基本都使用strong了

    相关文章

      网友评论

          本文标题:iOS 属性

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