首页 文章

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

提问于
浏览
352

ARC, strongweak 引入的属性有两个新的内存管理属性 .

除了 copy ,这显然是完全不同的东西, are there any differences between strong vs retain and weak vs assign?

根据我的理解,这里唯一的区别是 weak 将指定 nil 指针,而 assign 赢得't, which means the program will crash when I send a message to the pointer once it'已被释放 . 但是,如果我使用 weak ,这将不会发生,因为发送到 nil 的消息将不会执行任何操作 .

我不知道 strongretain 之间的任何差异 .

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

8 回答

  • 583

    来自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对象的弱引用 .

  • 38

    强者和保留者之间的区别:

    • 在iOS4中,strong等于保留

    • 这意味着您拥有该对象并将其保留在堆中,直到不再指向它为止

    • 如果你写保留它将自动工作就像强


    弱与分配之间的差异:

    • “弱”参考是您不保留的参考,只要其他人强烈指向它,您就会保留它

    • 当对象被“解除分配”时,弱指针自动设置为nil

    • "assign"属性属性告诉编译器如何合成属性的setter实现

  • 226

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

    • atomic //默认

    • 非原子的

    • strong =保留//默认

    • 保留

    • assign //默认

    • unsafe_unretained

    • 副本

    • 只读

    • readwrite //默认

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

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

    1.strong (iOS4 = retain )

    • 它说"keep this in the heap until I don't point to it anymore"

    • 换句话说" I'am the owner, you cannot dealloc this before aim fine with that same as retain"

    • 仅在需要保留对象时才使用strong .

    • 默认情况下,所有实例变量和局部变量都是强指针 .

    • 我们通常对UIViewControllers使用strong(UI项目的父项)

    • strong与ARC一起使用,它基本上可以帮助您,而不必担心对象的保留计数 . 完成后,ARC会自动为您释放它 . 使用关键字strong表示您拥有该对象 .

    例:

    @property (strong, nonatomic) ViewController *viewController;
    
    @synthesize viewController;
    

    2.weak -

    • 它说"keep this as long as someone else points to it strongly"

    • 与分配相同,不保留或释放

    • "weak"参考是您未保留的参考 .

    • 我们通常对IBOutlets使用弱(UIViewController的Childs) . 这是有效的,因为只要父对象存在,子对象才需要存在 .

    • 弱引用是一种引用,它不保护引用的对象不被垃圾收集器收集 .

    • 弱基本上是分配,一个没有保留的属性 . 除了释放对象时,弱指针自动设置为nil

    示例:

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

    Strong & Weak Explanation, Thanks to BJ Homer:

    想象一下,我们的对象是一只狗,狗想要逃跑(被解除分配) . 强壮的指针就像是狗的皮带 . 只要你的皮带附着在狗身上,狗就不会逃跑 . 如果五个人将他们的皮带连接到一只狗,(五个强指针指向一个物体),那么在所有五个皮带脱落之前,狗不会逃跑 . 另一方面,弱点就像小孩子指着那只狗说“看!一只狗!”只要狗仍然在皮带上,小孩子仍然可以看到狗,他们仍然会指向它 . 然而,一旦所有的皮带脱落,无论有多少小孩指着它,狗都会逃跑 . 一旦最后一个强指针(皮带)不再指向一个对象,该对象将被释放,并且所有弱指针都将被清零 .

    当我们使用弱者?

    你想要使用弱的唯一一次是,如果你想避免保留周期(例如父母保留孩子而孩子保留父母,所以两者都没有被释放) .

    3.retain = strong

    • 保留,旧值被释放并且被分配保留指定应该发送新值

    • 保留赋值,旧值发送-release

    • retain与strong相同 .

    • apple说如果你写保留它会自动转换/工作就像强大一样 .
      像"alloc"这样的

    • 方法包含一个隐含的"retain"

    例:

    @property (nonatomic, retain) NSString *name;
    
    @synthesize name;
    

    4.assign

    • assign是默认值,只是执行变量赋值

    • assign是一个属性属性,它告诉编译器如何合成属性的setter实现

    • 我将对C原始属性使用assign,对于对Objective-C对象的弱引用使用weak .

    例:

    @property (nonatomic, assign) NSString *address;
    
    @synthesize address;
    
  • 1

    Clang在Objective-C Automatic Reference Counting (ARC)上的文件清楚地解释了所有权限定符和修饰符:

    有四个所有权限定符:__ autoreleasing __strong __ * unsafe_unretained * __weak如果类型符合__autoreleasing,__strong或__weak,则该类型具有非法的所有权限定 .

    然后,声明属性有六个所有权修饰符:

    assign暗示__ * unsafe_unretained *所有权 . copy意味着__strong所有权,以及setter上复制语义的通常行为 . 保留意味着__strong所有权 . 强烈意味着__strong所有权 . * unsafe_unretained *暗示__ * unsafe_unretained *所有权 . 弱意味着__弱所有权 . 除弱点外,这些修饰符在非ARC模式下可用 .

    语义学上,所有权限定符在_414038中具有不同的含义:阅读,分配,初始化,销毁和移动,其中大多数时候我们只关心分配操作的差异 .

    评估赋值运算符时发生分配 . 语义因资格而异:对于__strong对象,首先保留新的指针;第二,左值加载了原始语义;第三,新的指针被存储到具有原始语义的左值中;最后,旧的指针被释放 . 这不是原子地执行的;必须使用外部同步,以便在并发加载和存储时使其安全 . 对于__weak对象,左值更新为指向新的指针,除非新的指针对象是当前正在进行解除分配的对象,在这种情况下,左值更新为空指针 . 这必须相对于对象的其他赋值,从对象读取以及到新指针的最终版本以原子方式执行 . 对于__ * unsafe_unretained *对象,新的指针对象使用原始语义存储到左值中 . 对于__autoreleasing对象,新的指针对象将被保留,自动释放,并使用原始语义存储到左值中 .

    阅读,初始化,毁灭和移动的另一个区别,请参阅Section 4.2 Semantics in the document .

  • 20

    非原子/原子

    • 非原子比原子快得多

    • 总是使用非原子,除非你有一个非常特殊的原子要求,这应该是罕见的(原子不同时由另一个线程设置)

    强/弱/分配

    • 使用strong来保留对象 - 虽然关键字retain是同义词,但最好使用strong

    • 如果你只想要一个指向对象的指针而不保留它,则使用weak - 对于避免保留周期(即委托)很有用 - 当对象被释放时它会自动将指针弄为零

    • 使用赋值为primatives - 完全像weak一样,除了它在释放时不会丢弃对象(默认设置)

    (可选)

    副本

    • 用它来创建对象的浅表副本

    • 总是将不可变属性设置为复制的良好实践 - 因为可变的版本可以传递给不可变属性,复制将确保您将始终处理不可变对象

    • 如果传入一个不可变对象,它将保留它 - 如果传入一个可变对象,它将复制它

    只读

    • 使用它来禁用属性的设置(如果存在违规则阻止代码编译)

    • 您可以通过直接通过其实例变量更改变量,或者在getter方法本身内更改getter传递的内容

  • 36

    强:

    • 属性不会销毁,但只有将属性设置为nil才会销毁对象

    • 默认情况下,所有实例变量和局部变量都是强指针 .

    • 仅在需要保留对象时才使用strong .

    • 我们通常对UIViewControllers使用strong(UI项目的父项)

    • IOS 4(非ARC)我们可以使用保留KeyWord

    • IOS 5(ARC)我们可以使用强关键字

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

    @synthesize viewController;

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

    • 我们通常对IBOutlets(UIViewController的Childs)和委托使用weak

    • 与分配相同,不保留或释放

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

    @synthesize myButton;

  • 1

    据我所知, strongretain 是同义词,所以它们完全相同 .

    然后 weak 几乎就像 assign ,但是在指向的对象之后自动设置为nil,被释放 .

    That means, you can simply replace them.

    However ,我遇到过一个特殊情况,我必须使用 assign ,而不是 weak . 假设我们有两个属性 delegateAssigndelegateWeak . 两者都存储了我们的代表,即拥有唯一强大的参考资料 . 代表正在解除分配,所以我们的 -dealloc 方法也被调用 .

    // Our delegate is deallocating and there is no other strong ref.
    - (void)dealloc {
        [delegateWeak doSomething];
        [delegateAssign doSomething];
    }
    

    委托已经处于释放过程中,但仍未完全取消分配 . 问题是 weak references to him are already nullified! 属性 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 变量如何工作以及它们何时无效 .

  • 2

    为了理解Strong和Weak引用,请考虑下面的示例,假设我们有一个名为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有一个强引用(我们在接口中使用@property声明)到myName(间接它有强引用“ABC”字符串) . 因此,在my.username处于活动状态之前,String myName不会从内存中释放 .

    • 弱参考

    现在考虑将myName分配给dummyName,这是一个弱引用,self.dummyName = myName;与强引用不同,Weak只保留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具有与之关联的Strong引用 .

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

    希望这可以帮助 .

相关问题