热门搜索 :
考研考公
您的当前位置:首页正文

iOS-Objective-C各种基本属性修饰符

来源:东饰资讯网

属性修饰符是每一个iOS程序员每天工作中都会用到的基础内容,也是初学iOS首先会接触到的内容。但在我面试过十多个已经有过一定工作经验iOS程序员时,发现他们居然还是对每个属性修饰符的原理和用法不甚明了,甚至有很多一直都在错用。我便想在此对其加以详细整理,如有问题请大家及时指出,多多沟通,共同进步。

1.@property是什么?

先来用@property定义一个基本的字符串属性

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

一个object的属性允许其他object监督和改变他的状态。但是在一个设计良好的面向对象程序中,直接访问一个object的内部状态是不可能的。相反,存取器(getter setter)方法是一个抽象相互作用object的底层数据。

@Property是声明属性的语法,它可以快速方便的为实例变量创建存取器,并允许我们通过点语法使用存取器。

存取器(accessor):指用于获取和设置实例变量的方法。用于获取实例变量值的存取器是getter,用于设置实例变量值的存取器是setter。

总之,@Property在定义属性时会自动生成get和set方法。可以使用self.Obj的get方法来调用属性,并且在set和get方法中对属性做了内存管理。而非@property定义的属性则不能使用Self.Obj来调用。

@synthesize关键字可以配合@Property来使用,用于在使用@property定义了属性后修改这个属性。例如

#import <Foundation/Foundation.h>  
#import "User.h"  
  
//有时候我们不想定义属性为_开头的  
//这时候我们就可以使用@synthesize,来修改我们想要的属性名  
  
//这时候属性_userName变成了$userName  
  
@implementation User  
@synthesize userName = $userName;  
  
@end  

2.@property中的关键字

原子属性(atomic)和非原子属性(nonatomic)

nonatomic
当一个变量声明为nonatomic时,意味着多个线程可以同时对其进行访问
当一个变量声明为nonatomic时,它是非线程安全型,访问速度快;
当一个变量声明为nonatomic时,当两个不同的线程对其访问时,容易失控。
atomic
当一个变量声明为atomic时,意味着在多线程中只能有一个线程能对它进行访问
当一个变量声明为atomic时,该变量为线程安全型,但是会影响访问速度,
当一个变量声明为atomic时,在非ARC编译环境下,需要设置访问锁来保证对该变量进行正确的get/set

nonatomic和atomic的对比

1.atomic:原子属性,为setter方法加锁(默认就是atomic);
nonatomic:非原子属性,不会为setter方法加锁。

2.atomic:线程安全,需要消耗大量的资源;
nonatomic:非线程安全,适合内存小的移动设备。

iOS开发的建议:所有属性都声明为nonatomic。
尽量避免多线程抢夺同一块资源。
尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力。

目前最常用的assign、copy、strong、weak

assign

用于非指针变量。用于基础数据类型 (例如NSInteger)和C数据类型(int, float, double, char, 等),另外还有id,其setter方法直接赋值,不进行任何retain操作。例如

@property (nonatomic,assign)NSInteger number;

weak

weak 用于指针变量,比assign多了一个功能,当对象消失后自动把指针变成nil,由于消息发送给空对象表示无操作,这样有效的避免了崩溃(野指针),为了解决原类型与循环引用问题.例如:

@property (nonatomic, weak)id<CustomDelegate> delegate;

注意:assign看起来跟weak一样,其实不能混用的,assign的变量在释放后并不设置为nil(和weak不同),当你再去引用时候就会发生错误,崩溃,EXC_BAD_ACCESS.

weak和assign都是引用计算不变,两个的差别在于,weak用于object type,就是指针类型,而assign用于简单的数据类型,如int BOOL 等。

copy

copy 用于指针变量,setter方法进行copy操作,与retain处理流程一样,先旧值release,再copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。copy是在你不希望a和b共享一块内存时会使用到。a和b各自有自己的内存。例如

@property (nonatomic,copy)NSArray *array;

strong

strong:strong和retain相似,只要有一个strong指针指向对象,该对象就不会被销毁。用于指针变量,setter方法对参数进行release旧值再retain新值。例如

@property (nonatomic,strong)NSMutableArray *dataArr;

注意:在实际运用中copy和strong的用法很多人在系统属性定义时会搞混,一般可变类型的属性用strong,不可变的用copy,如NSArray、NSString、NSDictionary用copy,NSMutableArray、NSMutableString用strong,不可变的属性用strong会导致在指向可变的内存地址后会变成可变属性。可变的属性用copy修饰后,指向不可变的内存地址会变成不可变的属性,容易导致出错。

其它不常用:

retain

retain 是在MRC中使用的强引用方式, 在 ARC 下基本等同于 strong。
_unsafeunretained,很少用到
unsafe_unretained: 其实质等同于assign。与weak的区别就是指向的对象如果被释放,其不会被置为nil,而导致悬空指针的出现。它是ARC模式下非对象属性的默认值。

readwrite | readonly

readwrite 可读可写,既有get方法,又有set方法。
readonly 只读,只有get方法,没有set方法。

3.其它常用到的修饰符

1.const变量修饰符。

只有只读权限,意思是这个参数只能读,不能修改内容,谁近修饰谁。

2.register

3.static 静态变量

有时候我们非常希望,用一个小变量记录某函数调用的次数,解决这个问题
方法1、可以使用全局变量;但是由于所有函数都可以修改它,对于较大程序出了问题不好调,所以使用全局变量并不好。
方法2、可以在目标函数中定义一个static变量(测试会发现这个变量的地址已经不再栈区,而是在数据区),每次进入函数让其++,static作用在局部变量前,函数结束此变量的值不清空,即改变了此变量的生命期,而且直到整个程序结束,并且此变量的值只有在定义它的函数中才可以被使用和重新赋值。

4.extern 扩展变量修饰符

extern int n;
extern可以扩展全局变量或函数的作用范围,只有全局变量或函数才可以用extern扩展
extern与register的区别

extern可以用来扩展函数的作用范围,可以跨文件扩展,前提是被扩展全局变量或者函数在定义时没有被static修饰!

5.MRC中

release 对象引用计数-1 如果为0释放内存
autorelease 对象引用计数-1 如果为0不马上释放,最近一个个pool时释放

6.其它

__block __weak__strong

__block

Blocks可以访问局部变量,但是不能修改
如果修改局部变量,需要加__block 例如

__block int i=0;
    [self setBlock:^{
       i=5;
    }];

__weak

若附有__weak 修饰符的变量所引用的对象被废弃,则将nil 赋值给该变量。
使用附有__weak 修饰符的变量,即是使用注册到autoreleasepool 中的对象。例如

__weak __typeof(&*self)weakSelf =self;

__strong

__strong 是缺省的关键词。用在block中方式属性被提前释放,例如

__strong typeof(weakSelf) self = weakSelf;

以上两种用法常搭配在防止block循环引用中,block循环引用的具体原理不在此做详细阐述,一般是在block中用self调用本类属性时会出现,一般用如下方法处理

__weak typeof(self) weakSelf = self;
    [self setBlock:^{
        __strong typeof(weakSelf) self = weakSelf;
        self.string = @"hello world";
    }];

常用的属性修饰符基本归纳整理完毕,关于其详细原理每个都可以写出大量篇幅,在此只整理出日常用法和基本原理,其它细节在后续内容中在做详细解释,文章中有引用到其它博客的部分语句,如有不足之处,还请大家多多指导,后续会逐渐补充。为更快提升自己,以后每周更新一篇,请大家监督😁。

Top