[英]Objective-C ARC: strong vs retain and weak vs assign
ARC为属性引入了两个新的内存管理属性,即strong
和weak
。
除了copy
,这显然是完全不同的, strong
和retain
之间以及weak
和assign
之间是否存在差异?
根据我的理解,这里唯一的区别是, weak
函数会将nil
分配给指针,而assign
不会,这意味着程序一旦释放后将消息发送给指针,程序就会崩溃。 但是,如果我使用weak
,那将永远不会发生,因为发送到nil
消息不会做任何事情。
我不知道strong
和retain
之间有什么区别。
有什么原因为什么我应该在新项目中使用assign
和retain
,还是被弃用?
在阅读了许多Stackoverflow帖子和演示应用程序以检查可变属性属性的文章之后,我决定将所有属性信息放在一起:
以下是详细的文章链接,您可以在其中找到上述所有属性,这些绝对会对您有所帮助。 非常感谢在这里给出最佳答案的所有人!!
1.strong(iOS4 =保留)
例:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.弱 -
范例:
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
强弱解释, 多亏了BJ Homer :
想象我们的对象是一只狗,那只狗想逃跑(被释放)。
强壮的指针就像拴在狗身上的皮带。 只要您将皮带拴在狗上,狗就不会跑开。 如果有五个人将皮带拴在一只狗上(五个强力指针指向一个物体),则只有将所有五个皮带分开后,狗才会逃跑。
另一方面,弱指针就像小孩指着狗说:“看!狗!” 只要那只狗仍系在皮带上,小孩子仍然可以看见它,他们仍会指向它。 但是,一旦所有的皮带都松开了,无论有多少小孩指向它,狗都会跑开。
一旦最后一个强指针(皮带)不再指向对象,该对象将被释放,所有弱指针将被清零。
什么时候用弱?
您唯一想使用弱函数的情况是,如果您想避免保留周期(例如,父母保留了孩子,而孩子保留了父母,因此都不会被释放)。
3.保留=强
例:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.分配
例:
@property (nonatomic, assign) NSString *address;
@synthesize address;
从过渡到ARC发行说明 (有关属性属性的部分中的示例)。
// The following declaration is a synonym for: @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;
如此strong
与retain
在属性声明中一样。
对于ARC项目我会用strong
,而不是retain
,我会用assign
对于C原始性能和weak
的,以Objective-C对象的弱引用。
据我所知, strong
和retain
是同义词,因此它们的作用完全相同 。
然后, weak
几乎就像assign
一样,但是在它所指向的对象被释放后自动设置为nil。
这意味着,您可以简单地替换它们。
但是 ,我遇到一种特殊情况,我必须使用assign
而不是weak
。 假设我们有两个属性delegateAssign
和delegateWeak
。 在这两者中都存储了我们的代表,即通过拥有唯一的强引用来拥有我们。 委托正在释放,因此我们的-dealloc
方法也被调用。
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething];
[delegateAssign doSomething];
}
委托已经在释放过程中,但是仍然没有完全释放。 问题在于, 对他的weak
引用已被废除! 属性delegateWeak
包含nil,但是delegateAssign
包含有效的对象(所有属性已经释放并无效,但仍然有效)。
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething]; // Does nothing, already nil.
[delegateAssign doSomething]; // Successful call.
}
这是一个非常特殊的情况,但它向我们揭示了那些weak
变量如何工作以及何时将其无效。
Clang关于Objective-C自动参考计数(ARC)的文档清楚地解释了所有权限定符和修饰符:
有四个所有权限定符:
- __ 自动释放
- __ 强
- __ * unsafe_unretained *
- __ 弱
如果类型具有__ 自动释放 ,__ 强或__ 弱的资格,那么它就是拥有所有权的资格。
然后,对声明的属性有六个所有权修饰符:
- 分配意味着__ * unsafe_unretained *所有权。
- 复制意味着__ 强大的所有权,以及setter上复制语义的通常行为。
- 保留意味着__ 强大的所有权。
- 强暗示__ 强所有权。
- * unsafe_unretained *意味着__ * unsafe_unretained *所有权。
- 弱意味着__所有权弱 。
除了weak以外 ,这些修饰符在非ARC模式下可用。
在语义上,所有权限定词在五个托管操作中具有不同的含义:读取,分配,初始化,销毁和移动,在大多数情况下,我们大多数时候只关心分配操作中的差异。
评估赋值运算符时发生转让 。 语义因条件而异:
- 对于__个强对象,首先保留新的pointe; 第二,左值加载了原始语义; 第三,用原始语义将新的pointe存储到左值中。 最后,老尖兵被释放。 这不是原子执行的; 面对并发的加载和存储,必须使用外部同步来使其安全。
- 对于__个弱对象,除非新指针是当前正在释放的对象,否则将更新左值以指向新指针,在这种情况下,左值将更新为空指针。 对于对象的其他分配,从对象的读取以及新指针的最终释放,这必须原子执行。
- 对于__ * unsafe_unretained *对象,使用原始语义将新的指针存储到左值中。
- 对于__ 自动释放对象,将使用原始语义保留,自动释放新指针并将其存储在左值中。
读取,初始化,破坏和移动方面的其他区别,请参阅文档中的第4.2节“语义” 。
为了理解强弱参考,请考虑以下示例,假设我们有一个名为displayLocalVariable的方法。
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
}
在上述方法中,myName变量的作用域仅限于displayLocalVariable方法,一旦方法完成,保存字符串“ ABC”的myName变量将从内存中释放。
现在,如果我们想在整个视图控制器生命周期中保留myName变量值,该怎么办。 为此,我们可以创建名为username的属性,该属性具有对变量myName的强引用(请参见以下代码中的self.username = myName;
),如下所示,
@interface LoginViewController ()
@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;
- (void)displayLocalVariable;
@end
@implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[self displayLocalVariable];
}
- (void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
现在,在上面的代码中,您可以看到myName已分配给self.username,并且self.username具有对myName的强引用(如我们在接口中使用@property在接口中声明的那样)(间接具有对“ ABC”字符串的强引用)。 因此,直到self.username处于活动状态时,字符串myName才会从内存中释放。
现在考虑将myName分配给一个虚弱引用的dummyName,self.dummyName = myName; 与强引用不同,弱将仅保留myName直到存在对myName的强引用。 请参阅以下代码以了解弱引用,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}
在上面的代码中,对myName的引用较弱(即self.dummyName对myName的引用较弱),但对myName没有强引用,因此self.dummyName将无法保存myName值。
现在再次考虑以下代码,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
self.dummyName = myName;
}
在上面的代码中,self.username具有对myName的强引用,因此,即使方法结束后,self.dummyName现在也具有myName的值,因为myName具有与之关联的Strong引用。
现在,每当我们对变量进行强引用时,其保留计数将增加一,并且该变量将不会被释放,保留计数将达到0。
希望这可以帮助。
示例:@property(强,非原子)ViewController * viewController;
@synthesize viewController;
默认情况下自动获取并设置为nil
示例:@属性(弱,非原子)IBOutlet UIButton * myButton;
@synthesize myButton;
强和保留之间的区别:
弱和赋值之间的区别:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.