Objective-C ARC:强vs保留,弱vs赋值

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

除了copy,这显然是完全不同的东西,在__ABC1 vs __ABC2和__ABC3 vs assign之间有什么区别吗?

根据我的理解,这里唯一的区别是weak会将nil分配给指针,而assign不会,这意味着一旦指针被释放,当我向指针发送消息时,程序将崩溃。但如果我使用weak,这将永远不会发生,因为消息发送到nil不会做任何事情。

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

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

205774 次浏览

来自过渡到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对象的弱引用。

据我所知,strongretain是同义词,所以它们对完全也是一样的。

然后weak几乎类似于assign,但在它所指向的对象被释放后自动设置为nil。

这意味着,你可以简单地更换它们。

然而,有一个特殊的情况,我遇到了,我必须使用assign,而不是weak。假设我们有两个属性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.
}

这是一个非常特殊的情况,但它揭示了那些weak变量是如何工作的,以及它们何时为空。

在阅读了许多Stackoverflow帖子和演示应用程序来检查变量属性属性后,我决定将所有属性信息放在一起:

  1. 原子 // 默认的
  2. 原子
  3. 强=保留/ /违约
  4. 保留
  5. 分配 // 默认的
  6. unsafe_unretained
  7. 复制
  8. 只读的
  9. 读写 // 默认的
下面是详细的文章链接,在那里你可以找到上面提到的所有属性,这肯定会对你有帮助。 非常感谢所有在这里给出最好答案的人!!< / p >

iOS中的可变属性属性或修饰符

1.strong (iOS4 = retain)

  • 它说"把这个放在堆里直到我不再指向它为止"
  • 换句话说,“我是所有者,你不能在此之前交易,目的很好,与保留相同”
  • 只有在需要保留对象时才使用strong。
  • 默认情况下,所有实例变量和局部变量都是强指针。
  • 我们通常用strong来表示UIViewControllers (UI项的父项)
  • strong与ARC一起使用,它基本上帮助你,不用担心对象的保留计数。当您使用完它时,ARC会自动为您释放它。使用关键字strong意味着您拥有该对象。

例子:

@property (strong, nonatomic) ViewController *viewController;


@synthesize viewController;

<强> 2.弱 - < / p >

  • 上面写着“只要有人强烈地指着它,你就留着它”
  • 和赋值一样,没有保留或释放
  • “弱”引用是指您不保留的引用。
  • 我们通常对iboutlet (UIViewController’s Childs)使用weak。这是因为只要父对象存在,子对象就需要存在。
  • 弱引用是指不保护被引用对象不被垃圾收集器回收的引用。
  • Weak本质上是赋值,一个未保留的属性。除了对象被释放时,弱指针被自动设置为nil

例子:

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


@synthesize myButton;

强,弱解释,感谢BJ Homer:

假设我们的对象是一只狗,这只狗想要逃跑 收回)。< / p > 强指针就像拴在狗身上的皮带。只要你有 拴上狗绳,狗就跑不掉了。如果有五个人 把他们的皮带拴在一只狗身上(五个强力指针指向一个物体), 直到五根皮带全部解开,狗才会跑开 弱指针,另一方面,就像小孩子指向 狗说:“看!一只狗!”只要狗还在就好 带着皮带,孩子们还能看到狗,他们还会指指点点 到它。不过,只要所有的皮带都被解开,狗就会跑 不管有多少小孩指着它。

当最后一个强指针(皮带)不再指向一个 对象,对象将被释放,所有弱指针将被 < / p > 0。

当我们用weak?

你唯一想要使用weak的时候是如果你想避免保留循环 (例如,父元素保留子元素,子元素保留父元素,所以两者都不会被释放)

3.保留=强大

  • 它被保留,旧的值被释放,它被分配retain指定应该发送的新值
  • 保留赋值和旧值sent -release
  • 保留就等于坚强。
  • 苹果说如果你写retain,它会自动转换/只像strong一样工作。
  • 像alloc这样的方法包含一个隐式的retain

例子:

@property (nonatomic, retain) NSString *name;


@synthesize name;

4.分配

  • Assign是默认值,它只执行变量赋值
  • Assign是一个属性属性,它告诉编译器如何合成属性的setter实现
  • 我将对C原语属性使用assign,对Objective-C对象的弱引用使用weak。

例子:

@property (nonatomic, assign) NSString *address;


@synthesize address;

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

有四个所有权限定符:

  • __生成
  • __强大的
  • __ * unsafe_unretained *
  • __

如果类型是限定的,则它是非平凡的所有权限定的 __生成, __强大的或__.

声明的属性有六个所有权修饰符:

  • 分配表示__*unsafe_unretained*所有权。
  • 复制暗示__强大的的所有权,以及复制语义在setter上的通常行为。
  • 保留表示__强大的的所有权。
  • 强大的表示__强大的的所有权。
  • *unsafe_unretained*表示__*unsafe_unretained*所有权。
  • 表示__的所有权。

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

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

赋值在赋值运算符求值时发生。的 语义根据限定的不同而不同:

  • 对于__强大的对象,首先保留新的指针;第二,左值装载了基本语义;第三,用基本语义将新指针存储到左值中;最后,旧的指针被释放。这不是原子地执行的;必须使用外部同步来保证在并发加载和存储时的安全性。
  • 对于__对象,左值被更新为指向新的指针,除非新指针是当前正在进行释放的对象,在这种情况下,左值被更新为空指针。这必须相对于对象的其他赋值、对象的读取以及新指针的最终释放而原子地执行。
  • 对于__*unsafe_unretained*对象,使用原语语义将新的指针存储到左值中。
  • 对于__生成对象,新的指针被保留、自动释放,并使用原语语义存储到左值中。

读取、初始化、销毁和移动的其他区别,请参考第4.2节文档含义

原子/原子

  • 非原子的比原子的快得多
  • 总是使用nonatomic,除非你对atomic有非常具体的要求,这应该是罕见的(atomic不能保证线程安全-只有当它同时被另一个线程设置时才会暂停访问属性)

强/弱/分配

  • 使用强大的来保留对象——尽管关键字retain是同义词,但最好使用strong代替
  • 如果你只想要一个指向对象的指针而不保留它,则使用 -这对于避免保留周期很有用。delegate)——当对象被释放时,它会自动空出指针
  • 对原语使用分配 -与weak完全相同,只是它在释放时不会清空对象(默认设置)

(可选)

复制

  • 使用它创建对象的浅拷贝
  • 始终将不可变属性设置为copy的好做法——因为可变版本可以传递到不可变属性中,copy将确保您始终处理不可变对象
  • 如果传入一个不可变对象,它将保留它-如果传入一个可变对象,它将复制它

只读的

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

strong和retain的区别:

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

weak和assign的区别:

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

强:

  • 属性不会销毁,但只有当你将属性设置为nil时,对象才会被销毁
  • 默认情况下,所有实例变量和局部变量都是强指针。
  • 只有在需要保留对象时才使用strong。
  • 我们通常用strong来表示UIViewControllers (UI项的父项)
  • IOS 4(非arc)我们可以使用保留关键字
  • IOS 5(ARC)我们可以使用强关键字
< p >的例子: @property (strong, nonatomic) ViewController * ViewController;

@ synthesize viewController;

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

  • 我们通常对iboutlet (UIViewController的子结点)和delegate使用weak
  • 和赋值一样,没有保留或释放
< p >的例子: @property(弱的,非原子的)IBOutlet UIButton *myButton

@ synthesize色;

要理解强引用和弱引用,请考虑下面的例子, 假设我们有一个方法名为displayLocalVariable.

 -(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
}

在上述方法中,myName变量的作用域仅限于displayLocalVariable方法,一旦方法完成,myName变量将从内存中释放字符串“ABC”。

现在如果我们想在视图控制器生命周期中保持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。用户名和自我。用户名对myName有强引用(正如我们在接口中使用@property声明的那样)(间接地,它对“ABC”字符串有强引用)。因此字符串myName直到self才会从内存中被释放。用户名已激活。

  • 弱引用
现在考虑将myName赋值给弱引用dummyName, self。dummyName = myName; 与强引用不同,弱引用将只保留myName,直到有对myName的强引用。 参见下面的代码来理解弱引用,

-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}

在上面的代码中,有对myName的弱引用(即。自我。dummyName对myName有弱引用),但没有对myName的强引用,因此是self。dummyName将不能保存myName值。

现在再次考虑下面的代码,

-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
self.dummyName = myName;
}

在以上代码中自我。username对myName有强引用,因此是self。即使在方法结束后,dummyName现在也会有一个myName值,因为myName有一个与之关联的强引用。

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

希望这能有所帮助。