[英]Objective-C ARC: strong vs retain and weak vs assign
There are two new memory management attributes for properties introduced by ARC, strong
and weak
. ARC为属性引入了两个新的内存管理属性,即strong
和weak
。
Apart from copy
, which is obviously something completely different, are there any differences between strong
vs retain
and weak
vs assign
? 除了copy
,这显然是完全不同的, strong
和retain
之间以及weak
和assign
之间是否存在差异?
From my understanding, the only difference here is that weak
will assign nil
to the pointer, while assign
won't, which means the program will crash when I send a message to the pointer once it's been released. 根据我的理解,这里唯一的区别是, weak
函数会将nil
分配给指针,而assign
不会,这意味着程序一旦释放后将消息发送给指针,程序就会崩溃。 But if I use weak
, this won't ever happen, because message send to nil
won't do anything. 但是,如果我使用weak
,那将永远不会发生,因为发送到nil
消息不会做任何事情。
I don't know about any differences between strong
and retain
. 我不知道strong
和retain
之间有什么区别。
Is there any reason why should I use assign
and retain
in new projects, or are the kind of being deprecated? 有什么原因为什么我应该在新项目中使用assign
和retain
,还是被弃用?
After reading so many articles Stackoverflow posts and demo applications to check variable property attributes, I decided to put all the attributes information together: 在阅读了许多Stackoverflow帖子和演示应用程序以检查可变属性属性的文章之后,我决定将所有属性信息放在一起:
Below is the detailed article link where you can find above mentioned all attributes, that will definitely help you. 以下是详细的文章链接,您可以在其中找到上述所有属性,这些绝对会对您有所帮助。 Many thanks to all the people who give best answers here!! 非常感谢在这里给出最佳答案的所有人!!
Variable property attributes or Modifiers in iOS iOS中的可变属性属性或修饰符
1.strong (iOS4 = retain ) 1.strong(iOS4 =保留)
Example: 例:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.weak - 2.弱 -
Example : 范例:
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
Strong & Weak Explanation, Thanks to BJ Homer : 强弱解释, 多亏了BJ Homer :
Imagine our object is a dog, and that the dog wants to run away (be deallocated). 想象我们的对象是一只狗,那只狗想逃跑(被释放)。
Strong pointers are like a leash on the dog. 强壮的指针就像拴在狗身上的皮带。 As long as you have the leash attached to the dog, the dog will not run away. 只要您将皮带拴在狗上,狗就不会跑开。 If five people attach their leash to one dog, (five strong pointers to one object), then the dog will not run away until all five leashes are detached. 如果有五个人将皮带拴在一只狗上(五个强力指针指向一个物体),则只有将所有五个皮带分开后,狗才会逃跑。
Weak pointers, on the other hand, are like little kids pointing at the dog and saying "Look! A dog!" 另一方面,弱指针就像小孩指着狗说:“看!狗!” As long as the dog is still on the leash, the little kids can still see the dog, and they'll still point to it. 只要那只狗仍系在皮带上,小孩子仍然可以看见它,他们仍会指向它。 As soon as all the leashes are detached, though, the dog runs away no matter how many little kids are pointing to it. 但是,一旦所有的皮带都松开了,无论有多少小孩指向它,狗都会跑开。
As soon as the last strong pointer (leash) no longer points to an object, the object will be deallocated, and all weak pointers will be zeroed out. 一旦最后一个强指针(皮带)不再指向对象,该对象将被释放,所有弱指针将被清零。
When we use weak? 什么时候用弱?
The only time you would want to use weak, is if you wanted to avoid retain cycles (eg the parent retains the child and the child retains the parent so neither is ever released). 您唯一想使用弱函数的情况是,如果您想避免保留周期(例如,父母保留了孩子,而孩子保留了父母,因此都不会被释放)。
3.retain = strong 3.保留=强
Example: 例:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.assign 4.分配
Example: 例:
@property (nonatomic, assign) NSString *address;
@synthesize address;
From the Transitioning to ARC Release Notes (the example in the section on property attributes). 从过渡到ARC发行说明 (有关属性属性的部分中的示例)。
// The following declaration is a synonym for: @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;
So strong
is the same as retain
in a property declaration. 如此strong
与retain
在属性声明中一样。
For ARC projects I would use strong
instead of retain
, I would use assign
for C primitive properties and weak
for weak references to Objective-C objects. 对于ARC项目我会用strong
,而不是retain
,我会用assign
对于C原始性能和weak
的,以Objective-C对象的弱引用。
As far as I know, strong
and retain
are synonyms, so they do exactly the same. 据我所知, strong
和retain
是同义词,因此它们的作用完全相同 。
Then the weak
is almost like assign
, but automatically set to nil after the object, it is pointing to, is deallocated. 然后, weak
几乎就像assign
一样,但是在它所指向的对象被释放后自动设置为nil。
That means, you can simply replace them. 这意味着,您可以简单地替换它们。
However , there is one special case I've encountered, where I had to use assign
, rather than weak
. 但是 ,我遇到一种特殊情况,我必须使用assign
而不是weak
。 Let's say we have two properties delegateAssign
and delegateWeak
. 假设我们有两个属性delegateAssign
和delegateWeak
。 In both is stored our delegate, that is owning us by having the only strong reference. 在这两者中都存储了我们的代表,即通过拥有唯一的强引用来拥有我们。 The delegate is deallocating, so our -dealloc
method is called too. 委托正在释放,因此我们的-dealloc
方法也被调用。
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething];
[delegateAssign doSomething];
}
The delegate is already in deallocation process, but still not fully deallocated. 委托已经在释放过程中,但是仍然没有完全释放。 The problem is that weak
references to him are already nullified! 问题在于, 对他的weak
引用已被废除! Property delegateWeak
contains nil, but delegateAssign
contains valid object (with all properties already released and nullified, but still valid). 属性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.
}
It is quite special case, but it reveal us how those weak
variables work and when they are nullified. 这是一个非常特殊的情况,但它向我们揭示了那些weak
变量如何工作以及何时将其无效。
Clang's document on Objective-C Automatic Reference Counting (ARC) explains the ownership qualifiers and modifiers clearly: Clang关于Objective-C自动参考计数(ARC)的文档清楚地解释了所有权限定符和修饰符:
There are four ownership qualifiers: 有四个所有权限定符:
- __ autoreleasing __ 自动释放
- __ strong __ 强
- __*unsafe_unretained* __ * unsafe_unretained *
- __ weak __ 弱
A type is nontrivially ownership-qualified if it is qualified with __ autoreleasing , __ strong , or __ weak . 如果类型具有__ 自动释放 ,__ 强或__ 弱的资格,那么它就是拥有所有权的资格。
Then there are six ownership modifiers for declared property: 然后,对声明的属性有六个所有权修饰符:
- assign implies __*unsafe_unretained* ownership. 分配意味着__ * unsafe_unretained *所有权。
- copy implies __ strong ownership, as well as the usual behavior of copy semantics on the setter. 复制意味着__ 强大的所有权,以及setter上复制语义的通常行为。
- retain implies __ strong ownership. 保留意味着__ 强大的所有权。
- strong implies __ strong ownership. 强暗示__ 强所有权。
- *unsafe_unretained* implies __*unsafe_unretained* ownership. * unsafe_unretained *意味着__ * unsafe_unretained *所有权。
- weak implies __ weak ownership. 弱意味着__所有权弱 。
With the exception of weak , these modifiers are available in non-ARC modes. 除了weak以外 ,这些修饰符在非ARC模式下可用。
Semantics wise, the ownership qualifiers have different meaning in the five managed operations : Reading, Assignment, Initialization, Destruction and Moving, in which most of times we only care about the difference in Assignment operation. 在语义上,所有权限定词在五个托管操作中具有不同的含义:读取,分配,初始化,销毁和移动,在大多数情况下,我们大多数时候只关心分配操作中的差异。
Assignment occurs when evaluating an assignment operator. 评估赋值运算符时发生转让 。 The semantics vary based on the qualification: 语义因条件而异:
- For __ strong objects, the new pointee is first retained; 对于__个强对象,首先保留新的pointe; second, the lvalue is loaded with primitive semantics; 第二,左值加载了原始语义; third, the new pointee is stored into the lvalue with primitive semantics; 第三,用原始语义将新的pointe存储到左值中。 and finally, the old pointee is released. 最后,老尖兵被释放。 This is not performed atomically; 这不是原子执行的; external synchronization must be used to make this safe in the face of concurrent loads and stores. 面对并发的加载和存储,必须使用外部同步来使其安全。
- For __ weak objects, the lvalue is updated to point to the new pointee, unless the new pointee is an object currently undergoing deallocation, in which case the lvalue is updated to a null pointer. 对于__个弱对象,除非新指针是当前正在释放的对象,否则将更新左值以指向新指针,在这种情况下,左值将更新为空指针。 This must execute atomically with respect to other assignments to the object, to reads from the object, and to the final release of the new pointee. 对于对象的其他分配,从对象的读取以及新指针的最终释放,这必须原子执行。
- For __*unsafe_unretained* objects, the new pointee is stored into the lvalue using primitive semantics. 对于__ * unsafe_unretained *对象,使用原始语义将新的指针存储到左值中。
- For __ autoreleasing objects, the new pointee is retained, autoreleased, and stored into the lvalue using primitive semantics. 对于__ 自动释放对象,将使用原始语义保留,自动释放新指针并将其存储在左值中。
The other difference in Reading, Init, Destruction and Moving, please refer to Section 4.2 Semantics in the document . 读取,初始化,破坏和移动方面的其他区别,请参阅文档中的第4.2节“语义” 。
To understand Strong and Weak reference consider below example, suppose we have method named as displayLocalVariable. 为了理解强弱参考,请考虑以下示例,假设我们有一个名为displayLocalVariable的方法。
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
}
In above method scope of myName variable is limited to displayLocalVariable method, once the method gets finished myName variable which is holding the string "ABC" will get deallocated from the memory. 在上述方法中,myName变量的作用域仅限于displayLocalVariable方法,一旦方法完成,保存字符串“ ABC”的myName变量将从内存中释放。
Now what if we want to hold the myName variable value throughout our view controller life cycle. 现在,如果我们想在整个视图控制器生命周期中保留myName变量值,该怎么办。 For this we can create the property named as username which will have Strong reference to the variable myName(see self.username = myName;
in below code), as below, 为此,我们可以创建名为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
Now in above code you can see myName has been assigned to self.username and self.username is having a strong reference(as we declared in interface using @property) to myName(indirectly it's having Strong reference to "ABC" string). 现在,在上面的代码中,您可以看到myName已分配给self.username,并且self.username具有对myName的强引用(如我们在接口中使用@property在接口中声明的那样)(间接具有对“ ABC”字符串的强引用)。 Hence String myName will not get deallocated from memory till self.username is alive. 因此,直到self.username处于活动状态时,字符串myName才会从内存中释放。
Now consider assigning myName to dummyName which is a Weak reference, self.dummyName = myName; 现在考虑将myName分配给一个虚弱引用的dummyName,self.dummyName = myName; Unlike Strong reference Weak will hold the myName only till there is Strong reference to myName. 与强引用不同,弱将仅保留myName直到存在对myName的强引用。 See below code to understand Weak reference, 请参阅以下代码以了解弱引用,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}
In above code there is Weak reference to myName(ie self.dummyName is having Weak reference to myName) but there is no Strong reference to myName, hence self.dummyName will not be able to hold the myName value. 在上面的代码中,对myName的引用较弱(即self.dummyName对myName的引用较弱),但对myName没有强引用,因此self.dummyName将无法保存myName值。
Now again consider the below code, 现在再次考虑以下代码,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
self.dummyName = myName;
}
In above code self.username has a Strong reference to myName, hence self.dummyName will now have a value of myName even after method ends since myName has a Strong reference associated with it. 在上面的代码中,self.username具有对myName的强引用,因此,即使方法结束后,self.dummyName现在也具有myName的值,因为myName具有与之关联的Strong引用。
Now whenever we make a Strong reference to a variable it's retain count get increased by one and the variable will not get deallocated retain count reaches to 0. 现在,每当我们对变量进行强引用时,其保留计数将增加一,并且该变量将不会被释放,保留计数将达到0。
Hope this helps. 希望这可以帮助。
Example: @property (strong, nonatomic) ViewController *viewController; 示例:@property(强,非原子)ViewController * viewController;
@synthesize viewController; @synthesize viewController;
By Default automatically get and set to nil 默认情况下自动获取并设置为nil
Example : @property (weak, nonatomic) IBOutlet UIButton *myButton; 示例:@属性(弱,非原子)IBOutlet UIButton * myButton;
@synthesize myButton; @synthesize myButton;
The differences between strong and retain: 强和保留之间的区别:
The differences between weak and assign: 弱和赋值之间的区别:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.