Objective-C ARC:强与保留、弱与分配

发布于 2024-12-28 00:26:31 字数 576 浏览 5 评论 0原文

ARC 引入了两个新的内存管理属性:strongweak

除了 copy 显然是完全不同的东西之外,strongretainweak 之间还有什么区别吗 code> vs assign

根据我的理解,这里唯一的区别是 weak 会将 nil 分配给指针,而 < code>assign 不会,这意味着当我发送消息时程序会崩溃一旦指针被释放。但如果我使用 weak,这种情况就不会发生,因为发送到 nil 的消息不会执行任何操作。

我不知道 strongretain 之间有什么区别。

我是否有任何理由应该在新项目中使用assignretain,或者这种类型已被弃用?

There are two new memory management attributes for properties introduced by ARC, strong and weak.

Apart from copy, which is obviously something completely different, are there any differences between strong vs retain and weak vs 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.

I don't know about any differences between strong and retain.

Is there any reason why should I use assign and retain in new projects, or are the kind of being deprecated?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

深海里的那抹蓝 2025-01-04 00:26:31

程序来检查可变属性属性后,我决定将所有属性信息放在一起:

  1. atomic //default
  2. nonatomicstrong
  3. =retain //
  4. defaultweakretainassign
  5. defaultunsafe_unretainedcopyreadonlyreadwrite
  6. //
  7. 演示应用
  8. 在阅读了这么多文章 Stackoverflow 帖子和
  9. //
  10. default

下面是详细的文章链接,您可以在其中找到上述所有属性,这肯定会对您有所帮助。
非常感谢所有在这里给出最佳答案的人!

iOS 中的变量属性或修饰符


1.strong (iOS4 = keep )

  • 它说“将其保留在堆中,直到我不再指向它”,
  • 换句话说“我是所有者,你不能dealloc this before 目标很好,与保留相同”
  • 仅当需要保留对象时才使用强。
  • 默认情况下,所有实例变量和局部变量都是强指针。
  • 我们通常对 UIViewControllers(UI 项的父级)使用 Strong,
  • strong 与 ARC 一起使用,它基本上可以帮助您,而不必担心对象的保留计数。当你使用完它后,ARC会自动为你释放它。使用关键字strong意味着你拥有该对象。

示例:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2.weak
-

  • 它说“只要其他人强烈指出它,就保留它”
  • 与分配相同,不保留或释放
  • “弱”引用是您不保留的引用。
  • 我们通常对IBOutlets(UIViewController的Childs)使用weak。这是有效的,因为子对象只需要与父对象存在一样长。
  • 弱引用是不能保护引用对象不被垃圾收集器收集的引用。
  • 弱本质上是分配,一个未保留的属性。除了当对象被释放时,弱指针会自动设置为 nil

示例:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Strong &解释不力,感谢 BJ Homer

想象我们的对象是一只狗,而狗想要逃跑(是
解除分配)。

强指针就像拴狗的皮带。只要你有
给狗拴上皮带,狗就不会逃跑。如果五个人
将皮带拴在一只狗身上(五个强指针指向一个物体),
然后,直到所有五个皮带都松开后,狗才会逃跑。

另一方面,弱指针就像小孩子指着
狗并说:“看!一只狗!”只要狗还在
拴着皮带,小孩子们仍然可以看到狗,他们仍然会指着
到它。然而,一旦所有的皮带都被松开,狗就会逃跑
不管有多少小孩子指着它,都走开。

一旦最后一个强指针(皮带)不再指向一个
对象,该对象将被释放,所有弱指针将被释放
归零。

我们什么时候用弱呢?

唯一需要使用weak的时候是如果你想避免引用循环
(例如,父级保留子级,子级保留父级,因此两者都不会被释放)。

3.retain=strong

  • 它被保留,旧值被释放并被分配retain指定应
  • 在分配时发送新值retain并发送旧值 -releaseretain
  • 与strong相同。
  • 苹果说,如果你写保留,它会自动转换/仅像强一样工作。
  • 像“alloc”这样的方法包含一个隐式的“retain”

示例:

@property (nonatomic, retain) NSString *name;

@synthesize name;

4.assign

  • allocate 是默认值,只是执行变量赋值
  • allocate 是一个属性属性,告诉编译器如何综合属性的 setter
  • 实现将使用 allocate 来表示 C 基元属性,使用weak 来表示对 Objective-C 对象的弱引用。

例子:

@property (nonatomic, assign) NSString *address;

@synthesize address;

After reading so many articles Stackoverflow posts and demo applications to check variable property attributes, I decided to put all the attributes information together:

  1. atomic //default
  2. nonatomic
  3. strong=retain //default
  4. weak
  5. retain
  6. assign //default
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite //default

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

1.strong (iOS4 = retain )

  • 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.

Example:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2.weak
-

  • 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

Example :

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Strong & Weak Explanation, Thanks to 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
(e.g. the parent retains the child and the child retains the parent so neither is ever released).

3.retain = strong

  • 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"

Example:

@property (nonatomic, retain) NSString *name;

@synthesize name;

4.assign

  • 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.

Example:

@property (nonatomic, assign) NSString *address;

@synthesize address;
苦笑流年记忆 2025-01-04 00:26:31

来自 过渡到 ARC 发行说明(示例中有关属性属性的部分)。

// The following declaration is a synonym for: @property(retain) MyClass *myObject;

@property(strong) MyClass *myObject;

因此,strong 与属性声明中的 retain 相同。

对于 ARC 项目,我会使用 strong 而不是 retain,对于 C 基元属性,我会使用 assign,对于 C 基元属性,我会使用 weak对 Objective-C 对象的弱引用。

From the Transitioning to ARC Release Notes (the example in the section on property attributes).

// 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.

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.

半步萧音过轻尘 2025-01-04 00:26:31

非原子/原子

  • 非原子比原子快得多
  • 总是使用非原子,除非您对原子有非常具体的要求,这应该很少见(原子不能保证线程安全 - 仅在同时访问属性时停止被另一个线程设置)

strong/weak/assign

  • 使用strong来保留对象 - 尽管关键字retain是同义词,但最好使用strong而不是
  • weak< /em>如果您只想要一个指向对象的指针而不保留它 - 对于避免保留循环(即委托)很有用 - 当对象被释放时它会自动将指针清零
  • 使用分配作为基元 - 完全相同弱,除非它在释放时不会将对象清零(默认设置)

(可选)

复制

  • 使用它来创建对象的浅表副本,
  • 好的做法是始终将不可变属性设置为复制 - 因为可变版本可以传递给不可变的属性, copy 将确保您始终处理不可变对象,
  • 如果传入不可变对象,它将保留它 - 如果传入可变对象,它将复制它

只读

  • 使用它禁用属性设置(如果存在违规,则阻止代码编译)
  • 您可以通过直接通过其实例变量或在 getter 方法本身中更改变量来更改 getter 提供的内容

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
  • 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)

(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
你与昨日 2025-01-04 00:26:31

据我所知,strongretain 是同义词,因此它们的作用完全相同

那么weak几乎就像assign一样,但是在它指向的对象被释放后自动设置为nil。

这意味着,您可以简单地替换它们。

但是,我遇到过一种特殊情况,我必须使用分配,而不是比。假设我们有两个属性 delegateAssigndelegateWeak。两者都存储了我们的委托,即通过拥有唯一的强引用来拥有我们。委托正在释放,因此我们的 -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.
}

这是一个非常特殊的情况,但它向我们揭示了这些弱变量如何工作以及它们何时被取消。

As far as I know, strong and retain are synonyms, so they do exactly the same.

Then the weak is almost like assign, but automatically set to nil after the object, it is pointing to, is deallocated.

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.

// 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).

// 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.

转身以后 2025-01-04 00:26:31

Clang 关于 Objective-C 自动引用计数 (ARC) 的文档清楚地解释了所有权限定符和修饰符:

有四个所有权限定符:

  • __自动释放
  • __
  • __*unsafe_unretained*
  • __

如果类型符合以下条件,则该类型具有非平凡所有权限定:
__自动释放、__或__

然后,声明的财产有六个所有权修饰符:

  • 分配意味着 __*unsafe_unretained* 所有权。
  • copy 意味着 __strong 所有权,以及 setter 上复制语义的通常行为。
  • 保留意味着__所有权。
  • strong 意味着 __strong 所有权。
  • *unsafe_unretained* 意味着 __*unsafe_unretained* 所有权。
  • 意味着__所有权。

除了之外,这些修饰符在非 ARC 模式下可用。

从语义上看,所有权限定符在读取、赋值、初始化、销毁和移动这五种托管操作中具有不同的含义,其中大多数时候我们只关心赋值操作的差异。

赋值在计算赋值运算符时发生。这
语义因资格而异:

  • 对于 __strong 对象,首先保留新的指针对象;其次,左值加载了原始语义;第三,新的指针被存储到具有原始语义的左值中;最后,旧的足尖运动员被释放。这不是原子执行的;必须使用外部同步来确保在并发加载和存储时的安全性。
  • 对于 __weak 对象,左值将更新为指向新的指针对象,除非新的指针对象是当前正在进行释放的对象,在这种情况下,左值将更新为空指针。对于对象的其他赋值、从对象读取以及新指针的最终释放,这必须以原子方式执行。
  • 对于 __*unsafe_unretained* 对象,新的指针对象使用原始语义存储到左值中。
  • 对于 __autoreleasing 对象,新的指针对象将被保留、自动释放,并使用原始语义存储到左值中。

其他在读取、初始化、销毁和移动方面的区别请参考文档中的第4.2节语义

Clang's document on Objective-C Automatic Reference Counting (ARC) explains the ownership qualifiers and modifiers clearly:

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.

Then there are six ownership modifiers for declared property:

  • assign implies __*unsafe_unretained* ownership.
  • copy implies __strong ownership, as well as the usual behavior of copy semantics on the setter.
  • retain implies __strong ownership.
  • strong implies __strong ownership.
  • *unsafe_unretained* implies __*unsafe_unretained* ownership.
  • weak implies __weak ownership.

With the exception of weak, these modifiers are available in non-ARC modes.

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; 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 __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.
  • 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.

只是我以为 2025-01-04 00:26:31

要理解强引用和弱引用,请考虑下面的示例,
假设我们有名为 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 存活之前,String 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 具有与其关联的强引用。

现在,每当我们对变量进行强引用时,它的保留计数都会增加 1,并且该变量不会被释放,保留计数达到 0。

希望这会有所帮助。

To understand Strong and Weak reference consider below example,
suppose we have method named as 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.

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,

@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.

  • 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,

-(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.

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.

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.

Hope this helps.

红ご颜醉 2025-01-04 00:26:31

强:

  • 属性不会销毁,但只有将属性设置为 nil 时,对象才会被销毁
  • 默认情况下,所有实例变量和局部变量都是强指针。
  • 仅当需要保留对象时才使用强。
  • 我们通常对 UIViewControllers(UI 项目的父级)使用 Strong
  • IOS 4(非 ARC)我们可以使用 Retain KeyWord
  • IOS 5(ARC) 我们可以使用 Strong 关键字

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

@synthesize viewController;

Weak

默认情况下会自动获取并设置为 nil

  • 我们通常对 IBOutlet(UIViewController 的子级)使用weak,并委托
  • 与分配相同的东西,不保留或释放

示例:
@property(弱,非原子)IBOutlet UIButton *myButton;

@synthesize myButton;

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

Example:
@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

Weak

By Default automatically get and set to nil

  • We generally use weak for IBOutlets (UIViewController's Childs) and delegate
  • the same thing as assign, no retain or release

Example :
@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

情绪失控 2025-01-04 00:26:31

Strong和retain的区别:

  • 在iOS4中,strong等于retain,
  • 它意味着你拥有该对象,并将其保留在堆中,直到不再指向它为止。
  • 如果你写了retain,它会自动像strong一样工作

。弱引用和赋值:

  • “弱”引用是指你不保留的引用,只要其他人强指向它,你就保留它。
  • 当对象被“释放”时,弱指针会自动设置为
  • nil " property 属性告诉编译器如何合成属性的 setter 实现

The differences between strong and 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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文