ARC引入的属性有两个新的内存管理属性,strong
和weak
。
除了copy
,这显然是完全不同的, strong
与retain
和weak
与assign
之间是否有任何差异?
根据我的理解,这里唯一的区别是weak
会将nil
分配给指针,而assign
则不会,这意味着当我发送消息时程序会崩溃一旦它被释放就指向指针。但是,如果我使用weak
,则不会发生这种情况,因为发送给nil
的邮件将不会执行任何操作。
我不知道strong
和retain
之间存在任何差异。
我有什么理由在新项目中使用assign
和retain
,还是被弃用?
答案 0 :(得分:594)
在阅读了很多文章Stackoverflow帖子和演示应用程序来检查变量属性属性后,我决定将所有属性信息放在一起:
下面是详细的文章链接,您可以在其中找到上述所有属性,这些内容肯定会对您有所帮助。 非常感谢所有在这里给出最佳答案的人!!
1.strong(iOS4 =保留)
示例:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
<强> 2.weak 强> -
示例:
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
强大&amp;弱解释,Thanks to BJ Homer:
想象一下,我们的对象是一只狗,狗想要逃跑(是的 解除分配)。
强壮的指针就像是狗的皮带。只要你有 皮带附着在狗身上,狗不会逃跑。如果五个人 将他们的皮带系在一只狗上,(一个物体的五个强指针), 然后狗不会逃跑,直到所有五个皮带脱落。
另一方面,弱点就像小孩子指着的那样 狗,说“看!一只狗!”只要狗还在上 皮带,小孩子仍然可以看到狗,他们仍然会指出 它。然而,一旦所有的皮带脱落,狗就跑了 不管有多少小孩指着它。一旦最后一个强指针(皮带)不再指向一个 对象,对象将被释放,所有弱指针都将被释放 归零。
当我们使用弱者时?
你唯一想要使用弱的方法是,如果你想避免保留周期 (例如,父母保留孩子,孩子保留父母,所以两者都没有被释放)。
3.retain = strong
示例:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.assign
示例:
@property (nonatomic, assign) NSString *address;
@synthesize address;
答案 1 :(得分:228)
来自Transitioning to ARC Release Notes(属性属性部分中的示例)。
// 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对象的弱引用。
答案 2 :(得分:39)
据我所知,strong
和retain
是同义词,因此完全相同。
然后weak
几乎就像assign
,但在指向的对象被解除分配后自动设置为nil。
这意味着,您只需更换它们即可。
然而,我遇到过一个特例,我必须使用assign
,而不是weak
。假设我们有两个属性delegateAssign
和delegateWeak
。两者都存储了我们的代表,即拥有唯一强大的参考资料。该委托正在解除分配,因此我们也调用了-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
变量如何工作以及它们何时无效。
答案 3 :(得分:38)
答案 4 :(得分:20)
Clang关于Objective-C Automatic Reference Counting (ARC)的文件清楚地解释了所有权限定符和修饰符:
有四个所有权限定符:
- __ 自动释放
- __ 强
- __ * unsafe_unretained *
- __ 弱
如果类型符合条件,则该类型具有非平凡的所有权限定条件 __ 自动释放,__ 强或__ 弱。
然后,声明的属性有六个所有权修饰符:
- assign 暗示__ * unsafe_unretained *所有权。
- copy 意味着__ 强所有权,以及setter上复制语义的常见行为。
- 保留表示__ 强所有权。
- strong 意味着__ 强所有权。
- * unsafe_unretained *暗示__ * unsafe_unretained * ownership。
- 弱意味着__ 弱所有权。
除 weak 外,这些修饰符在非ARC模式下可用。
语义明智,所有权限定符在五个管理操作中具有不同的含义:阅读,分配,初始化,销毁和移动,其中大多数时候我们只关心分配操作的差异。
评估赋值运算符时会发生赋值。该 语义因资格而异:
- 对于__ 强对象,首先保留新的指针;第二,左值加载了原始语义;第三,新的指针被存储到具有原始语义的左值中;最后,老指针被释放了。这不是原子地执行的;必须使用外部同步,以便在并发加载和存储时使其安全。
- 对于__ 弱对象,左值更新为指向新的指针,除非新指针是当前正在进行解除分配的对象,在这种情况下,左值更新为空指针。这必须相对于对象的其他赋值,从对象读取以及新指针的最终版本以原子方式执行。
- 对于__ * unsafe_unretained *对象,新的指针对象使用原始语义存储到左值中。
- 对于__ autoreleasing 对象,新的指针对象将被保留,自动释放,并使用原始语义存储到左值中。
阅读,初始,毁灭和移动的另一个区别,请参阅Section 4.2 Semantics in the document。
答案 5 :(得分:3)
要了解强弱参考,请考虑以下示例, 假设我们有一个名为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处于活动状态时,字符串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。
希望这会有所帮助。
答案 6 :(得分:2)
实施例: @property(强,非原子)ViewController * viewController;
@synthesize viewController;
默认自动获取并设置为nil
示例: @property(弱,非原子)IBOutlet UIButton * myButton;
@synthesize myButton;
答案 7 :(得分:1)
强者和保留者之间的区别:
弱与分配之间的差异: