ios Objective-C ARC:强 vs 保留和弱 vs 分配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8927727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Objective-C ARC: strong vs retain and weak vs assign
提问by Jakub Arnold
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
,这显然是完全不同的东西,vs和vs之间有什么区别吗?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. But if I use weak
, this won't ever happen, because message send to nil
won't do anything.
根据我的理解,这里唯一的区别是weak
将分配nil
给指针,而不会分配assign
,这意味着当我向指针发送消息后,程序将崩溃。但是如果我使用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
,还是被弃用?
采纳答案by JeremyP
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 项目,我将使用C 原始属性和对 Objective-C 对象的弱引用,strong
而不是retain
使用。assign
weak
回答by swiftBoy
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帖子和demo应用检查变量属性的文章,我决定把所有的属性信息放在一起:
- atomic //default
- nonatomic
- strong=retain //default
- weak
- retain
- assign //default
- unsafe_unretained
- copy
- readonly
- readwrite //default
- 原子 //默认
- 非原子的
- 强=保留//默认
- 虚弱的
- 保持
- 赋值 //默认
- unsafe_unretained
- 复制
- 只读
- 读写 //默认
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!!
下面是详细的文章链接,您可以在其中找到上述所有属性,这肯定会对您有所帮助。非常感谢所有在这里给出最佳答案的人!!
1.strong (iOS4 = retain )
1.强(iOS4 = 保留)
- it says "keep this in the heap until I don't point to it anymore"
- in other words " I'am the owner, you cannot dealloc this before aim fine with that same as retain"
- You use strong only if you need to retain the object.
- By default all instance variables and local variables are strong pointers.
- We generally use strong for UIViewControllers (UI item's parents)
- strong is used with ARC and it basically helps you , by not having to worry about the retain count of an object. ARC automatically releases it for you when you are done with it.Using the keyword strong means that you own the object.
- 它说“把它放在堆里,直到我不再指向它”
- 换句话说,“我是所有者,在瞄准与保留相同的目标之前,您无法解除分配”
- 只有在需要保留对象时才使用 strong。
- 默认情况下,所有实例变量和局部变量都是强指针。
- 我们通常对 UIViewControllers 使用 strong(UI 项的父项)
- strong 与 ARC 一起使用,它基本上可以帮助您,不必担心对象的保留计数。当您完成它时,ARC 会自动为您释放它。使用关键字 strong 表示您拥有该对象。
Example:
例子:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.weak-
2.弱——
- it says "keep this as long as someone else points to it strongly"
- the same thing as assign, no retain or release
- A "weak" reference is a reference that you do not retain.
- We generally use weak for IBOutlets (UIViewController's Childs).This works because the child object only needs to exist as long as the parent object does.
- a weak reference is a reference that does not protect the referenced object from collection by a garbage collector.
- Weak is essentially assign, a unretained property. Except the when the object is deallocated the weak pointer is automatically set to nil
- 它说“只要有人强烈指出它就保留它”
- 与分配相同的东西,没有保留或释放
- “弱”引用是您不保留的引用。
- 我们一般对IBOutlets(UIViewController的Childs)使用weak。这是因为只要父对象存在,子对象就需要存在。
- 弱引用是不保护被引用对象不被垃圾收集器收集的引用。
- 弱本质上是赋值,一种未保留的属性。除了对象被释放时,弱指针自动设置为 nil
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.
想象一下我们的对象是一只狗,而这只狗想要逃跑(被释放)。
强指针就像狗的皮带。只要你把皮带拴在狗身上,狗就不会逃跑。如果五个人将他们的皮带拴在一只狗上(五个强烈的指针指向一个物体),那么在所有五根皮带都松开之前,狗不会逃跑。
另一方面,弱指针就像小孩子指着狗说“看!一只狗!” 只要狗仍然被拴在皮带上,小孩子仍然可以看到狗,他们仍然会指向它。然而,一旦所有的皮带都松开了,不管有多少小孩指着它,这只狗都会逃跑。
一旦最后一个强指针(leash)不再指向一个对象,该对象将被释放,所有弱指针将被清零。
When we use weak?
当我们使用弱?
The only time you would want to use weak, is if you wanted to avoid retain cycles (e.g. the parent retains the child and the child retains the parent so neither is ever released).
您唯一想要使用弱的情况是,如果您想避免保留循环(例如,父项保留子项而子项保留父项,因此两者都不会被释放)。
3.retain = strong
3.保持=强
- it is retained, old value is released and it is assigned retain specifies the new value should be sent
- retain on assignment and the old value sent -release
- retain is the same as strong.
- apple says if you write retain it will auto converted/work like strong only.
- methods like "alloc" include an implicit "retain"
- 它被保留,旧值被释放并分配给它保留指定应发送的新值
- 保留分配和旧值发送 - 释放
- 保留与强相同。
- 苹果说如果你写保留它只会自动转换/像强一样工作。
- 像“alloc”这样的方法包括一个隐含的“retain”
Example:
例子:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.assign
4.赋值
- assign is the default and simply performs a variable assignment
- assign is a property attribute that tells the compiler how to synthesize the property's setter implementation
- I would use assign for C primitive properties and weak for weak references to Objective-C objects.
- assign 是默认值,只是执行变量赋值
- assign 是一个属性属性,它告诉编译器如何合成属性的 setter 实现
- 我会对 C 原始属性使用assign,对Objective-C 对象的弱引用使用weak。
Example:
例子:
@property (nonatomic, assign) NSString *address;
@synthesize address;
回答by Vadoff
nonatomic/atomic
非原子/原子
- nonatomic is much faster than atomic
- always use nonatomic unless you have a very specific requirement for atomic, which should be rare (atomic doesn't guarantee thread safety - only stalls accessing the property when it's simultaneously being set by another thread)
- 非原子比原子快得多
- 除非您对原子有非常具体的要求,否则始终使用非原子,这应该很少见(原子不保证线程安全 - 只有在另一个线程同时设置属性时才会停止访问该属性)
strong/weak/assign
强/弱/分配
- use strongto retain objects - although the keyword retain is synonymous, it's best to use strong instead
- use weakif you only want a pointer to the object without retaining it - useful for avoid retain cycles (ie. delegates) - it will automatically nil out the pointer when the object is released
- use assignfor primatives - exactly like weak except it doesn't nil out the object when released (set by default)
- 使用strong来保留对象 - 尽管关键字 retain 是同义词,但最好使用 strong 代替
- 如果您只想要一个指向对象的指针而不保留它,请使用weak- 有助于避免保留循环(即委托) - 当对象被释放时,它会自动清除指针
- 对原始对象使用assign- 与weak 完全一样,只是它在释放时不会清除对象(默认设置)
(Optional)
(可选的)
copy
复制
- use it for creating a shallow copy of the object
- good practice to always set immutable properties to copy - because mutable versions can be passed into immutable properties, copy will ensure that you'll always be dealing with an immutable object
- if an immutable object is passed in, it will retain it - if a mutable object is passed in, it will copy it
- 用它来创建对象的浅拷贝
- 始终将不可变属性设置为复制的良好做法 - 因为可变版本可以传递给不可变属性,复制将确保您始终处理不可变对象
- 如果传入一个不可变对象,它将保留它 - 如果传入一个可变对象,它将复制它
readonly
只读
- use it to disable setting of the property (prevents code from compiling if there's an infraction)
- you can change what's delivered by the getter by either changing the variable directly via its instance variable, or within the getter method itself
- 使用它来禁用属性的设置(如果存在违规,则阻止代码编译)
- 您可以通过直接通过其实例变量或在 getter 方法本身中更改变量来更改 getter 提供的内容
回答by Tricertops
As far as I know, strong
and retain
are synonyms, so they do exactlythe 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
. Let's say we have two properties delegateAssign
and 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.
但是,我遇到过一种特殊情况,我必须使用assign
, 而不是weak
. 假设我们有两个属性delegateAssign
和delegateWeak
。在两者中都存储了我们的委托,即通过拥有唯一的强引用来拥有我们。委托正在释放,因此我们的-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!Property delegateWeak
contains nil, but delegateAssign
contains valid object (with all properties already released and nullified, but still valid).
委托已经在解除分配过程中,但仍未完全解除分配。问题是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.
}
It is quite special case, but it reveal us how those weak
variables work and when they are nullified.
这是一个非常特殊的情况,但它向我们展示了这些weak
变量是如何工作的以及它们何时被取消。
回答by Mingming
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*
- __weak
A type is nontrivially ownership-qualified if it is qualified with __autoreleasing, __strong, or __weak.
有四个所有权限定符:
- __自动释放
- __强
- __*unsafe_unretained*
- __弱
如果一个类型用 __ autoreleasing、 __ strong或 __ weak限定,则它是非平凡的所有权限定。
Then there are six ownership modifiers for declared property:
那么声明的财产有六个所有权修饰符:
- assignimplies __*unsafe_unretained* ownership.
- copyimplies __strongownership, as well as the usual behavior of copy semantics on the setter.
- retainimplies __strongownership.
- strongimplies __strongownership.
- *unsafe_unretained* implies __*unsafe_unretained* ownership.
- weakimplies __weakownership.
With the exception of weak, these modifiers are available in non-ARC modes.
- 分配意味着 __*unsafe_unretained* 所有权。
- 复制意味着 __强所有权,以及 setter 上复制语义的通常行为。
- 保留意味着__强所有权。
- 强意味着__强所有权。
- *unsafe_unretained* 暗示 __*unsafe_unretained* 所有权。
- 弱意味着__弱所有权。
除了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.
从语义上讲,所有权限定符在五个托管操作中具有不同的含义:读取、赋值、初始化、销毁和移动,其中大多数时候我们只关心赋值操作的差异。
Assignmentoccurs when evaluating an assignment operator. The semantics vary based on the qualification:
- For __strongobjects, the new pointee is first retained; second, the lvalue is loaded with primitive semantics; third, the new pointee is stored into the lvalue with primitive semantics; 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 __weakobjects, 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.
- For __autoreleasingobjects, the new pointee is retained, autoreleased, and stored into the lvalue using primitive semantics.
分配评估赋值运算符时出现。语义因资格而异:
- 对于__强对象,首先保留新的指针;其次,左值加载了原始语义;第三,用原始语义将新的指针存储到左值中;最后,旧指针被释放。这不是以原子方式执行的;面对并发加载和存储,必须使用外部同步来确保安全。
- 对于 __弱对象,左值被更新为指向新的指针,除非新的指针是当前正在释放的对象,在这种情况下左值被更新为空指针。这必须相对于对对象的其他分配、从对象读取以及对新指针的最终释放以原子方式执行。
- 对于 __*unsafe_unretained* 对象,使用原始语义将新指针存储到左值中。
- 对于 __自动释放对象,新的指针被保留、自动释放并使用原始语义存储到左值中。
The other difference in Reading, Init, Destruction and Moving, please refer to Section 4.2 Semantics in the document.
其他Reading、Init、Destruction、Moving的区别请参考文档中的4.2语义。
回答by Mahadev Mandale
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. 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,
现在,如果我们想在整个视图控制器生命周期中保存 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
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). Hence String myName will not get deallocated from memory till self.username is alive.
现在在上面的代码中,您可以看到 myName 已分配给 self.username 并且 self.username 具有对 myName 的强引用(正如我们在接口中使用@property 声明的那样)(间接地它对“ABC”字符串具有强引用)。因此 String myName 不会从内存中释放,直到 self.username 还活着。
- Weak reference
- 弱参考
Now consider assigning myName to dummyName which is a Weak reference, self.dummyName = myName; Unlike Strong reference Weak will hold the myName only till there is Strong reference to myName. See below code to understand Weak reference,
现在考虑将 myName 分配给 dummyName,这是一个弱引用,self.dummyName = myName; 与强引用不同,Weak 只会保留 myName 直到对 myName 有强引用。请参阅下面的代码以了解弱引用,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}
In above code there is Weak reference to myName(i.e. 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 有一个与之关联的强引用。
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.
现在,每当我们对一个变量进行强引用时,它的保留计数都会增加 1,并且该变量不会被释放,保留计数会达到 0。
Hope this helps.
希望这可以帮助。
回答by Nikunj Patel
Strong:
强的:
- Property will not Destroy but Only once you set the property to nil will the object get destroyed
- By default all instance variables and local variables are strong pointers.
- You use strong only if you need to retain the object.
- We generally use strong for UIViewControllers (UI item's parents)
- IOS 4 (non-ARC) We Can Use Retain KeyWord
- IOS 5(ARC) We Can Use Strong Keyword
- 属性不会销毁,但只有当您将属性设置为 nil 时,对象才会被销毁
- 默认情况下,所有实例变量和局部变量都是强指针。
- 只有在需要保留对象时才使用 strong。
- 我们通常对 UIViewControllers 使用 strong(UI 项的父项)
- IOS 4 (non-ARC) 我们可以使用 Retain KeyWord
- IOS 5(ARC) 我们可以使用强关键字
Example: @property (strong, nonatomic) ViewController *viewController;
示例:@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
@synthesize 视图控制器;
Weak
虚弱的
By Default automatically get and set to nil
默认情况下自动获取并设置为 nil
- We generally use weak for IBOutlets (UIViewController's Childs) and delegate
- the same thing as assign, no retain or release
- 我们一般对IBOutlets(UIViewController的Childs)和delegate使用weak
- 与分配相同的东西,没有保留或释放
Example : @property (weak, nonatomic) IBOutlet UIButton *myButton;
示例:@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
@synthesize myButton;
回答by Chen Rui
The differences between strong and retain:
strong和retain的区别:
- In iOS4, strong is equal to retain
- It means that you own the object and keep it in the heap until don't point to it anymore
- If you write retain it will automatically work just like strong
- 在iOS4中,强等于保留
- 这意味着您拥有该对象并将其保留在堆中,直到不再指向它
- 如果你写保留它会像强一样自动工作
The differences between weak and assign:
弱和分配的区别:
- A “weak” reference is a reference that you don't retain and you keep it as long as someone else points to it strongly
- When the object is “deallocated”, the weak pointer is automatically set to nil
- A "assign" property attribute tells the compiler how to synthesize the property's setter implementation
- “弱”引用是您不保留的引用,只要其他人强烈指向它,您就会保留它
- 当对象被“解除分配”时,弱指针自动设置为 nil
- “assign”属性属性告诉编译器如何合成属性的setter实现