我是 Obj-C 的新手,所以我的第一个问题是:
对象指针的声明strong
和声明之间有什么区别?weak
@property
还有,什么nonatomic
意思?
从气球的角度考虑强引用和弱引用可能会有所帮助。
只要至少有一个人抓着一根绳子,气球就不会飞走。持有字符串的人数是保留计数。当没有人抓住绳子时,气球会飞走(dealloc)。许多人可以为同一个气球系上绳子。您可以使用强引用和弱引用在被引用对象上获取/设置属性和调用方法。
强引用就像抓住气球的绳子。只要你握住气球上的绳子,它就不会飞走。
弱参考就像看气球。你可以看到它,访问它的属性,调用它的方法,但是你没有那个气球的字符串。如果每个抓住绳子的人都放开,气球就会飞走,你就不能再接触它了。
强引用(您将在大多数情况下使用)意味着您想要“拥有”您使用此属性/变量引用的对象。只要您使用强引用指向它,编译器就会注意您分配给此属性的任何对象都不会被破坏。只有将属性设置为nil
,对象才会被销毁(除非一个或多个其他对象也持有对它的强引用)。
相反,使用弱引用表示您不想控制对象的生命周期。您弱引用的对象仅存在,因为至少有一个其他对象持有对它的强引用。一旦不再是这种情况,对象就会被销毁,并且您的弱属性将自动设置为nil
. iOS 中最常见的弱引用用例是:
委托属性,通常被弱引用以避免保留循环,以及
视图控制器的主视图的子视图/控件,因为这些视图已经被主视图强持有。
原子与非原子是指编译器为属性综合的 getter 和 setter 方法的线程安全性。atomic (默认)告诉编译器使访问器方法线程安全(通过在访问 ivar 之前添加锁),而 nonatomic 则相反。非原子的优点是性能稍高。在 iOS 上,Apple 几乎所有属性都使用非原子,因此一般建议您也这样做。
strong:将传入的值分配给它,它将保留传入的值并释放实例变量的现有值
weak:将传入的值分配给它而不保留它。
所以基本的区别是新变量的保留。一般来说,您想要保留它,但在某些情况下您不想拥有它,否则您将获得保留周期并且无法释放对象的内存。例如。obj1 保留 obj2,obj2 保留 obj1。为了解决这种情况,您使用弱引用。
一个虚拟的答案:-
我认为上面的答案给出了解释,所以我只想告诉你在哪里使用STRONG
以及在哪里使用WEAK
:
使用Weak
:-
1. 代表 2. 出口 3. 子视图 4. 控件等
使用Strong
:-
未包含在任何地方的剩余WEAK
。
strong和weak,这些关键字围绕着Objective-C 中的对象所有权
什么是对象所有权?
指针变量意味着它们指向的对象的所有权。
每当指针变量指向一个对象时,该对象就有一个所有者并且将保持活动状态。这被称为强参考。
变量可以选择不获取它指向的对象的所有权。不拥有对象所有权的变量称为弱引用。
在这里,Apple 文档使用各种示例解释了弱属性和强属性之间的区别:
在这里,在此博客中,作者已将所有属性收集在同一位置。这将有助于比较属性特征:
http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html
强是默认值。只要有一个指向它的强指针,一个对象就保持“活动”。
弱指定不保持被引用对象活动的引用。当对象没有强引用时,弱引用设置为 nil。
要理解强引用和弱引用,请考虑以下示例,假设我们有名为 displayLocalVariable 的方法。
-(void)displayLocalVariable
{
UIView* myView = [[UIView alloc] init];
NSLog(@"myView tag is = %ld", myView.tag);
}
在上述方法中,myView 变量的作用域仅限于 displayLocalVariable 方法,一旦方法完成,持有 UIView 对象的 myView 变量将从内存中释放。
现在,如果我们想在视图控制器的整个生命周期中保存 myView 变量怎么办。为此,我们可以创建名为 usernameView 的属性,该属性将对变量 myView 进行强引用(参见下面的代码) @property(nonatomic,strong) UIView* usernameView;
,self.usernameView = myView;
如下所示,
@interface LoginViewController ()
@property(nonatomic,strong) UIView* usernameView;
@property(nonatomic,weak) UIView* dummyNameView;
- (void)displayLocalVariable;
@end
@implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[self displayLocalVariable];
}
- (void)displayLocalVariable
{
UIView* myView = [[UIView alloc] init];
NSLog(@"myView tag is = %ld", myView.tag);
self.usernameView = myView;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
现在在上面的代码中,您可以看到 myView 已分配给 self.usernameView 并且 self.usernameView 对 myView 具有强引用(正如我们在接口中使用 @property 声明的那样)。因此 myView 不会从内存中释放,直到 self.usernameView 还活着。
现在考虑将 myName 分配给作为弱引用的 dummyNameView,self.dummyNameView = myView;
与强引用不同,Weak 将只保留 myView,直到有对 myView 的强引用。请参阅下面的代码以了解弱引用,
-(void)displayLocalVariable
{
UIView* myView = [[UIView alloc] init];
NSLog(@"myView tag is = %ld", myView.tag);
self.dummyNameView = myView;
}
在上面的代码中有对 myView 的弱引用(即 self.dummyNameView 对 myView 有弱引用)但没有对 myView 的强引用,因此 self.dummyNameView 将无法保存 myView 值。
现在再次考虑下面的代码,
-(void)displayLocalVariable
{
UIView* myView = [[UIView alloc] init];
NSLog(@"myView tag is = %ld", myView.tag);
self.usernameView = myView;
self.dummyNameView = myView;
}
在上面的代码中 self.usernameView 有一个对 myView 的强引用,因此 self.dummyNameView 现在即使在方法结束后也会有一个 myView 的值,因为 myView 有一个与之关联的强引用。
现在,每当我们对变量进行强引用时,它的保留计数都会增加 1,并且该变量不会被释放,直到它的保留计数达到 0。
希望这可以帮助。
强:基本上与我们用来从/向其他类获取或发送数据的属性一起使用。 弱:通常所有的出口,连接都是来自接口的弱类型。
Atomic:这种类型的属性用于我们不想将我们的出口或对象共享到不同的同时线程中的情况。换句话说,原子实例使我们的属性一次处理一个线程。希望它对你有帮助。