Objective-C中强项和弱项之间的差异


308

我是Obj-C的新手,所以我的第一个问题是:

之间有什么区别strong,并weak@property对象的指针的声明?

还有,这nonatomic是什么意思?


19
实际上,这是一个很好的问题,有时,我们忘记了强/弱和原子/非原子偏好的基本概念.... :)谢谢您提醒我们有关此问题……
andikurnia 2013年

10
@JackyBoy有趣的是,在Google上建议的简单搜索使我在这里大声笑。#circularreference
Jason Renaldo

10
我倾向于不信任Google上的许多答案,但总是引用SO来获得智能答案
JeffK 2013年

Answers:


641

强大的引用(在大多数情况下将使用)表示您希望“拥有”使用此属性/变量引用的对象。编译器会注意,只要您使用强引用指向它,分配给该属性的任何对象都不会被破坏。只有将属性设置为,nil该对象才会被销毁(除非一个或多个其他对象也对该对象具有强烈的引用)。

相反,使用弱引用,则表示您不想控制对象的生命周期。您所弱引用的对象仅能生存,因为至少有另一个对象对此对象具有强引用。一旦不再是这种情况,该对象将被销毁,并且您的弱属性将自动设置为nil。iOS中弱引用的最常见用例是:

  1. 委派属性,这些属性通常被弱引用以避免保留周期,并且

  2. 视图控制器主视图的子视图/控件,因为这些视图已经由主视图牢牢占据。

原子与非原子是指编译器为该属性综合的getter和setter方法的线程安全性。原子(默认)告诉编译器使访问器方法成为线程安全的(通过在访问ivar之前添加锁),而非原子的则相反。非原子的优点是性能略高。在iOS上,Apple几乎对所有属性都使用非原子性,因此一般建议您也这样做。


28
@Bourne:这取决于您所说的线程安全性。atomic保证可以同时从多个线程安全地读取和写入该属性。这并不意味着其属性全部atomic都是自动的线程安全的对象。
Ole Begemann

3
很棒的细节。我想直到现在我才真正得到它。谢谢。
ahmedalkaff

1
根据Apple的文档,原子和非原子应该与线程安全同义。developer.apple.com/library/ios/documentation/cocoa/conceptual/...
穆尔塔扎胡尔希德·侯赛因

5
“注意:属性原子性不是对象线程安全的同义词。” developer.apple.com/library/ios/documentation/cocoa/conceptual/...
GS

为什么我们不想要的时候就不删除实例呢?为什么我们不希望不只是从气球中抽出空气或销毁气球,为什么还要关心附带的绳子?我们只需要数据。
Ashish Pisey '19

706

考虑气球的强引用和弱引用可能会有所帮助。

只要至少有一个人抓住气球上的绳子,气球就不会飞走。持有琴弦的人数是保留人数。当没有人抓住弦时,气球将飞走(取消分配)。许多人可以在同一气球上放绳子。您可以使用强引用和弱引用来获取/设置引用对象的属性并调用方法。

强有力的参考就像坚持那个气球的弦一样。只要您抓住气球上的绳子,它就不会飞走。

弱引用就像看着气球。您可以看到它,访问它的属性,调用它的方法,但是该气球没有任何字符串。如果所有人都松开了绳子,气球就会飞走,您将无法再使用它。


68
+2(如果可以的话)。说真的,真的很有创意!
Con Antonakos 2014年

25
在iOS开发了一年半之后,我想我现在才清楚地了解了什么strongweak真正的意思。
Isuru 2014年

17
@ X.Li保持周期就像您有2根琴弦,其中一根是您拥有的(因此您拥有此气球),另一根是该气球拥有的(因此此气球拥有您)。既然您只能使用自己的琴弦,那么如果不想放走气球,该如何放走气球呢?因此,最好是拥有气球(强),而不拥有气球(弱)。当您想放手时,只需剪断字符串即可:)
snakeninny14年

5
阅读他的个人资料,他是iOS老师。很有创意的解释!
脱帽

3
我认为原子与非原子之间的关系可以说是一间公共厕所,它有多个门,一个厕所位于中央。一旦有人从一个门进入厕所,如果他不想经历尴尬的时刻,他不妨将所有其他门锁定在厕所中。大声笑。感谢您阅读这个胡说八道的类比。
陈李咏

24

强大:为其分配传入值,它将保留传入值并释放实例变量的现有值

:将分配传入的值而不保留它。

因此,基本区别是保留新变量。通常,您想要保留它,但是在某些情况下,您不想保留它,否则您将获得保留周期,并且无法释放对象的内存。例如。obj1保留obj2,而obj2保留obj1。要解决这种情况,您可以使用弱引用。


12

一个虚拟的答案:-

我认为上面的答案给出了解释,所以我只想告诉您在哪里使用STRONG和在哪里使用WEAK

使用Weak:- 1.代表团2.奥特莱斯3. 4.子视图控件等。

使用Strong:- 保留在不包含的所有地方WEAK


2
等等包含了什么:P
Rajneesh071

3
webView,mapView等
shubham mishra

4
实际上,我们拖放到情节
提要

8

,这些关键字围绕Objective-C中的对象所有权

什么是对象所有权?

指针变量暗示它们指向的对象的所有权。

  • 当方法(或函数)具有指向对象的局部变量时,该变量被称为拥有所指向的对象。
  • 当一个对象的实例变量指向另一个对象时,带有指针的对象被称为拥有所指向的对象。

每当指针变量指向一个对象时,该对象就会拥有所有者并保持活动状态。这被称为参考。

变量可以选择不获取其指向的对象的所有权。不拥有对象所有权的变量称为引用。

在这里查看详细说明解密@property和属性



6

强大默认设置为。只要有很强的指针指向对象,该对象就保持“活动”状态。

指定了一个引用,该引用不能使引用的对象保持活动状态。如果没有对对象的强引用,则将弱引用设置为nil。


2

为了理解强弱参考,请考虑以下示例,假设我们有一个名为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的接口中声明的那样)。因此,直到self.usernameView处于活动状态时,myView才会从内存中释放。

  • 参考不足

现在考虑将myName分配给弱引用的dummyNameView,self.dummyNameView = myView;与强引用不同,弱将仅保留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具有与之关联的Strong引用。

现在,只要我们对变量进行强引用,它的保留计数就会增加一,并且直到保留计数达到0时,变量才会被释放。

希望这可以帮助。


2019-07-25 12:33:15.479002 + 0530 StrongAndWeak [6329:245483]我的名字是= ABC 2019-07-25 12:33:15.479226 + 0530 StrongAndWeak [6329:245483]我的名字是强烈的= ABC 2019- 07-25 12:33:15.479418 + 0530 StrongAndWeak [6329:245483]我的名字叫weak = ABC,在此您告诉弱财产没有myname的值。但是我得到两个引用的myname作为ABC的值。 ..?您能给出更明确的答案吗?...提前感谢
Madhu_Nani19年

@Raviteja_DevObal ARC不承诺立即进行操作(即取消分配字符串@“ ABC”),但是肯定会在以后取消分配...
Mahadev Mandale

@Raviteja_DevObal作为解释,这里的字符串是一个不好的例子。我已经用UIView对象更新了答案,希望对您有所帮助。
Mahadev Mandale

1

Strong:基本上与Properties一起使用,我们曾经从另一个类获取数据或向另一个类发送数据。 :通常所有接口的连接都是接口的弱类型。

非原子的:此类类型的属性用于当我们不想将我们的出口或对象共享到不同的同时线程中的情况。换句话说,非原子实例使我们的属性可以一次处理一个线程。希望它对您有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.