美文网首页
strong 和 weak

strong 和 weak

作者: 大荣纸 | 来源:发表于2017-04-13 21:01 被阅读41次

    strong:使得对象的引用计数器 +1

    weak:不会使得对象的引用计数器 +1

    将一个对象通过 addXXX 方法添加数组中时,同样会使得对象的引用计数器+1

    所以,当将一个实例添加到self.view中时,引用计数器已经为1了,视图是由self.view持有的,如果,一旦添加一个属性,声明一个单独的引用来指向对象时,声明为strong会导致计数器再+1。当视图需要从self.view中移除掉时,引用计数器-1,但计数器依然会因为这个strong引用的存在而是1,一个不再出现在界面的视图,因为计数器不为0而驻留在内容中,是比较浪费资源的,所以,添加到self.view中的子视图,再添加一个属性引用时,就不要使用strong,而最好选择weak。

    (weak和strong)不同的是 当一个对象不再有strong类型的指针指向它的时候 它会被释放  ,即使还有weak型指针指向它。

    一旦最后一个strong型指针离去 ,这个对象将被释放,所有剩余的weak型指针都将被清除。

    首先有一点,在OC中,如果对象没有强引用,就会被自动释放,那么为什么控件还可以设为weak?

    1. 从storyboard或者xib上创建控件,在控件放在view上的时候,已经形成了如下的引用关系,以UIButton为例:

    UIViewController->UIView->subView->UIButton

    然后你为这个UIButton声明一个weak属性

    @property(nonatomic,weak)IBOOutletUIButton*btn;

    相当于xib/sb对这个Button是强引用,你声明的属性对它是弱引用。

    2.手动创建控件

    a). 将控件声明成strong

    @property(nonatomic,strong)UIButton*btn;

    那么你在实现这个控件时只需这样:

    _btn = [[UIButton alloc]init];[self.view addSubview:_btn]

    b). 将控件声明成weak

    @property(nonatomic,weak) UIButton *btn;

    那么你在实现这个控件时需要这样:

    UIButton *button = [[UIButton alloc]init];_btn = button;[self.view addSubview:_btn];

    IBOutlet的属性一般可以设为weak是因为它已经被view引用了,除非view被释放,否则IBOutlet的属性也不会被释放,另外IBOutlet属性的生命周期和view应该是一致的,所以IBOutlet属性一般设为weak。

    简单的说,如果IBOutlet对象是nib/sb scene的拥有者(File’s owner)所持有的对象,那么很显然拥有者必须“拥有”对象的指针,因此属性应设置为strong。而其他的IBOutlet对象的属性需要设置为weak,因为拥有者并不需要“拥有”他们的指针。举例来说,UIViewController的view属性是strong,因为controller要直接拥有view。而添加到view上的subviews,作为IBOutlet只需要设置为weak就可以了,因为他们不是controller直接拥有的。直接拥有subviews的是controller的view,ARC会帮助管理内存。

    第一种情形前面已经解释过了,对于第二种,通俗点将,就是controller需要直接控制某一个subview并且将subview添加到其他的view tree上去。

    单纯从ARC的角度思考,用weak也是很显然的:因为subview添加到view上时,view会“拥有”subview。当然,给IBOutlet属性设置为strong也没有错,“纠结谁对谁错“的问题可能需要上升到模式或者编码习惯的问题,已经超出本文的范围。

    assign: 用于非指针变量。用于

    基础数据类型 (例如NSInteger)和C数据类型(int, float, double, char, 等),另外还有id

    如:

    @property (nonatomic, assign) int number;

    @property (nonatomic, assign) id className;//id必须用assign

    反正记住:前面不需要加 “*” 的就用assign吧

    retain:用于指针变量。就是说你定义了一个变量,然后这个变量在程序的运行过程中会被更改,并且影响到其他方法。一般是用于字符串( NSString,NSMutableString),数组(NSMutableArray,NSArray),字典对象,视图对象(UIView ),控制器对象(UIViewController)等 比如:

     @property (nonatomic,retain) NSString * myString; 

    @property (nonatomic, retain) UIView * myView; 

    @property (nonatomic, retain) UIViewController * myViewController; 

    xcode 4.2不支持ARC,所以会频繁使用retain来修饰,用完释放掉,而xcode4.3以后支持ARC,可以使用retian,不需要手动释放内存,系统会自动为你完成,如果你在xcode4.3以后上面开发,retian和strong都是一样的,没区别 

    strong和weak:

     事实上 @property(nonatomic,strong) MyClass *myObject;就是相当于

    @property(nonatomic,retain) MyClass *myObject;

    @property(nonatomic, weak )id delegate;就是相当于

    @property(nonatomic,assign )id delegate; 

     copy:这个东西估计是大部分人最不容易搞明白的东西,我也搞不明白。听别人说这个东西基本不用了,效果其实和retain没什么两样,唯一的区别就是copy只用于NSString而不能用于NSMutableString。 不过好像当一个类继承NSObject,那么这个类里面的属性需要使用copy,比如: 

    #import#import@interface Annotation : NSObject{

    CLLocationCoordinate2D coordinate;

    NSString *title;

    NSString *subtitle;

    }

    @property (nonatomic) CLLocationCoordinate2D coordinate;

    @property (nonatomic, copy) NSString *title;

    @property (nonatomic, copy) NSString *subtitle;

    @end

    反正以后就这么用就是了

    反正就记住一点:xcode4.2用retain和assign ;xcode4.3或以上版本用strong与weak 。以前用xcode4.2开发程序的程序员会习惯用retain ,所以代码都是retian的,新手如果从xcode4.3学起的话就用strong与weak  吧,这里面讲的区别有些不对的地方。

    readonly:此标记说明属性是只读的,默认的标记是读写,如果你指定了只读,在@implementation中只需要一个读取器。或者如果你使用@synthesize关键字,也是有读取器方法被解析。而且如果你试图使用点操作符为属性赋值,你将得到一个编译错误。

    readwrite:此标记说明属性会被当成读写的,这也是默认属性。设置器和读取器都需要在@implementation中实现。如果使用@synthesize关键字,读取器和设置器都会被解析。

    assign:此标记说明设置器直接进行赋值,这也是默认值。在使用垃圾收集的应用程序中,如果你要一个属性使用assign,且这个类符合NSCopying协议,你就要明确指出这个标记,而不是简单地使用默认值,否则的话,你将得到一个编译警告。这再次向编译器说明你确实需要赋值,即使它是可拷贝的。

    retain:指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。(原因很明显,retain会增加对象的引用计数,而基本数据类型或者Core Foundation对象都没有引用计数——译者注)。

    copy:它指出,在赋值时使用传入值的一份拷贝。拷贝工作由copy方法执行,此属性只对那些实行了NSCopying协议的对象类型有效。更深入的讨论,请参考“复制”部分。

    nonatomic:指出访问器不是原子操作,而默认地,访问器是原子操作。这也就是说,在多线程环境下,解析的访问器提供一个对属性的安全访问,从获取器得到的返回值或者通过设置器设置的值可以一次完成,即便是别的线程也正在对其进行访问。如果你不指定nonatomic,在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了nonatomic,那么访问器只是简单地返回这个值。

    atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。

    所以property的属性默认是:readwrite,assign, atomic

    相关文章

      网友评论

          本文标题:strong 和 weak

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