简体   繁体   English

Objective-C ARC:强vs保留,弱vs分配

[英]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为属性引入了两个新的内存管理属性,即strongweak

Apart from copy , which is obviously something completely different, are there any differences between strong vs retain and weak vs assign ? 除了copy ,这显然是完全不同的, strongretain之间以及weakassign之间是否存在差异?

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 . 我不知道strongretain之间有什么区别。

Is there any reason why should I use assign and retain in new projects, or are the kind of being deprecated? 有什么原因为什么我应该在新项目中使用assignretain ,还是被弃用?

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帖子和演示应用程序以检查可变属性属性的文章之后,我决定将所有属性信息放在一起:

  1. atomic //default 原子//默认
  2. nonatomic 非原子
  3. strong=retain //default strong =保留//默认
  4. weak
  5. retain 保留
  6. assign //default 分配//默认
  7. unsafe_unretained unsafe_unretained
  8. copy 复制
  9. readonly 只读
  10. readwrite //default readwrite //默认

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 =保留)

  • 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. 仅在需要保留对象时才使用Strong。
  • By default all instance variables and local variables are strong pointers. 默认情况下,所有实例变量和局部变量都是强指针。
  • We generally use strong for UIViewControllers (UI item's parents) 我们通常对UIViewControllers(UI项目的父对象)使用强
  • strong is used with ARC and it basically helps you , by not having to worry about the retain count of an object. strong与ARC一起使用,它基本上可以帮助您,而不必担心对象的保留计数。 ARC automatically releases it for you when you are done with it.Using the keyword strong means that you own the object. 完成后,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. 我们通常对IBOutlets(UIViewController的Childs)使用弱函数,这是有效的,因为子对象只需要与父对象一样存在即可。
  • 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 除了对象被释放时,弱指针会自动设置为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. 一旦最后一个强指针(皮带)不再指向对象,该对象将被释放,所有弱指针将被清零。

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.保留=强

  • 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 保留赋值并发送旧值-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" 像“分配”这样的方法包括一个隐式的“保留”

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 Assign是一个属性属性,它告诉编译器如何综合该属性的setter实现
  • I would use assign for C primitive properties and weak for weak references to Objective-C objects. 我将对C基本属性使用assign,对Objective-C对象的弱引用使用weak。

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. 如此strongretain在属性声明中一样。

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. 据我所知, strongretain是同义词,因此它们的作用完全相同

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 . 假设我们有两个属性delegateAssigndelegateWeak 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变量如何工作以及何时将其无效。

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 strong to retain objects - although the keyword retain is synonymous, it's best to use strong instead 使用strong来保留对象-尽管关键字retain是同义词,但是最好使用strong来代替
  • use weak if 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 assign for primatives - exactly like weak except it doesn't nil out the object when released (set by default) 使用指定的primatives -释放时完全一样软弱只是它不为零出对象(默认设置)

(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传递的内容

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才会从内存中释放。

  • Weak reference 参考不足

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. 希望这可以帮助。

Strong: 强大:

  • Property will not Destroy but Only once you set the property to nil will the object get destroyed 属性不会销毁,但是只有将属性设置为nil,对象才会被销毁
  • By default all instance variables and local variables are strong pointers. 默认情况下,所有实例变量和局部变量都是强指针。
  • You use strong only if you need to retain the object. 仅在需要保留对象时才使用Strong。
  • We generally use strong for UIViewControllers (UI item's parents) 我们通常对UIViewControllers(UI项目的父对象)使用强
  • IOS 4 (non-ARC) We Can Use Retain KeyWord IOS 4(非ARC)我们可以使用保留关键字
  • IOS 5(ARC) We Can Use Strong Keyword IOS 5(ARC)我们可以使用强关键字

Example: @property (strong, nonatomic) ViewController *viewController; 示例:@property(强,非原子)ViewController * viewController;

@synthesize viewController; @synthesize viewController;

Weak

By Default automatically get and set to nil 默认情况下自动获取并设置为nil

  • We generally use weak for IBOutlets (UIViewController's Childs) and delegate 我们通常对IBOutlets(UIViewController的Childs)使用弱函数并进行委托
  • the same thing as assign, no retain or release 与分配相同,没有保留或释放

Example : @property (weak, nonatomic) IBOutlet UIButton *myButton; 示例:@属性(弱,非原子)IBOutlet UIButton * myButton;

@synthesize myButton; @synthesize myButton;

The differences between strong and retain: 强和保留之间的区别:

  • In iOS4, strong is equal to retain 在iOS4中,强等于保留
  • 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 如果您写保留,它将自动像强

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 当对象被“取消分配”时,弱指针将自动设置为nil
  • A "assign" property attribute tells the compiler how to synthesize the property's setter implementation “赋值”属性的属性告诉编译器如何综合属性的setter实现

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM