ARC声明属性关键字详解(strong,weak,unsafe_unretained,copy)

ARC声明属性关键字详解(strong,weak,unsafe_unretained,copy)

在iOS开发过程中,属性的定义往往与retain, assign, copy有关,我想大家都很熟悉了,在此我也不介绍,网上有很多相关文章。

但是在iOS 5中加入ARC,产生了几个新的关键字strong, weak, unsafe_unretained.  我们可以将其与以前的关键字对应学习: strong与retain类似,weak和unsafe_unretained这两个新关键字与assign类似功能差不多(但还是有点区别)。在iOS5中用这些新的关键字,就可以不用手动管理内存了。

(1)

strong关键字与retain关似,用了它,引用计数自动+1,用实例更能说明一切


  1. @property (nonatomic, strong) NSString *string1;
  2. @property (nonatomic, strong) NSString *string2;

有这样两个属性


  1. @synthesize string1;
  2. @synthesize string2;

猜一下下面代码将输出什么结果?


  1. self.string1 = @"String 1";
  2. [self.string2 = self.string1;
  3. [self.string1 = nil;
  4. [NSLog(@"String 2 = %@", self.string2);

结果是:String 2 = String 1

由于string2是strong定义的属性,所以引用计数+1,使得它们所指向的值都是@"String 1", 如果你对retain熟悉的话,这理解并不难。

(2)

接着我们来看weak关键字:

如果这样声明两个属性:


  1. @property (nonatomic, strong) NSString *string1;
  2. @property (nonatomic, weak) NSString *string2;

并定义


  1. @synthesize string1;
  2. @synthesize string2;

再来猜一下,下面输出是什么?


  1. self.string1 = [[NSString alloc] initWithUTF8String:"string 1"];
  2. elf.string2 = self.string1;
  3. self.string1 = nil;
  4. NSLog(@"String 2 = %@", self.string2);

结果是:String 2 = null

分析一下,由于 self.string1与self.string2指向同一地址,且string2没有retain内存地址,而self.string1=nil释放 了内存,所以string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。在 c/c++开发过程中,为何大牛都说指针的空间释放了后,都要将指针赋为NULL. 在这儿用weak关键字帮我们做了这一步。

(3)

接着我们来看unsafe_unretained

从名字可以看出,unretained且unsafe,由于是unretained所以与weak有点类似,但是它是unsafe的,什么是unsafe的呢,下面看实例。

如果这样声明两个属性:

并定义


  1. @property (nonatomic, strong) NSString *string1;
  2. @property (nonatomic, unsafe_unretained) NSString *string2;

再来猜一下,下面的代码会有什么结果?


  1. self.string1 = [[NSString alloc] initWithUTF8String:"string 1"];
  2. self.string2 = self.string1;
  3. self.string1 = nil;
  4. NSLog(@"String 2 = %@", self.string2);

请注意,在此我并没有叫你猜会有什么输出,因为根本不会有输出,你的程序会crash掉。 原因是什么,其实 就是野指针造成的,所以野指针是可怕的。为何会造成野指针呢?同于用unsafe_unretained声明的指针,由于 self.string1=nil已将内存释放掉了,但是string2并不知道已被释放了,所以是野指针。然后访问野指针的内存就造成crash.  所以尽量少用unsafe_unretained关键字。

(4)

在声明属性(declaring properties)的时候strong, weak, unsafe_unretained会经常被用到。默认所有的属性都是assign(基本类型)或者strong(oc对象)。

在声明局部变量的时候你也可以使用这些存储说明符(storage specifiers),但是你需要对说明符做一点修改。strong等效的嵌入说明符为__strong,weak等效的嵌入说明符为__weak,unsafe_unretained等效的嵌入说明符为__unsafe_unretained。(记住这些关键字是以2个下划线开头) 默认,所有的局部变量(local variables)是__strong变量。

__weak, __strong 用来修饰变量,此外还有 __unsafe_unretained, __autoreleasing 都是用来修饰变量的。
__strong 是缺省的关键词。
__weak 声明了一个可以自动 nil 化的弱引用。
__unsafe_unretained 声明一个弱应用,但是不会自动nil化,也就是说,如果所指向的内存区域被释放了,这个指针就是一个野指针了。
__autoreleasing 用来修饰一个函数的参数,这个参数会在函数返回的时候被自动释放。

ARC声明属性时,对于基本数据类型默认关键字是 (atomic,readwrite,assign)
ARC声明属性时,对于普通的OC对象默认关键字是 (atomic,readwrite,strong)

示例:

@property (nonatomic) int supportOrientation;           默认是assign,因为是基础数据类型,必须是assign

@property (readonly) UIImage* rightImage;                                     默认是atomic

@property (nonatomic) bolo_BasePlayerControlView* ctrlView;            默认是strong

@property (nonatomic, weak) id<WatchVideoDetailDelegate> delegate;         代理使用weak

(5)

LLVM官网给出的一些示意,arc里也可以使用retain等关键字

------------------------------在属性中使用以下关键字的效用-------------------------

  • assign implies __unsafe_unretained ownership.
  • copy implies __strong ownership, as well as the usual behavior of copy semantics on the setter.
  • retain implies __strong ownership.
  • strong implies __strong ownership.
  • unsafe_unretained implies __unsafe_unretained ownership.
  • weak implies __weak ownership.

assign 等同unsafe_unretained

copy的作用和MRC一样,同时又有strong的效果

retain 等同 strong

weak与unsafe_unretained的区别在于,weak会将被释放指针赋值为nil,而unsafe_unretained则会成为野指针。

时间: 2024-10-25 05:17:07

ARC声明属性关键字详解(strong,weak,unsafe_unretained,copy)的相关文章

ARC机制之__strong详解

ARC机制之__strong详解 __strong  解析: 默认情况下,一个指针都会使用 __strong 属性,表明这是一个强引用.这意味着,只要引用存在,对象就不能被销毁.这是一种所期望的行为:当所有(强)引用都去除时,对象才能被收集和释放. 不过, 有时我们却希望禁用这种行为:一些集合类不应该增加其元素的引用,因为这会引起对象无法释放.在这种情况下,我们需要使用弱引用(不用担心,内置的集合类 就是这么干的),使用 __weak 关键字.NSHashTable 就是一个例子.当被引用的对象

Delphi 关键字详解

absolute//它使得你能够创建一个新变量, 并且该变量的起始地址与另一个变量相同. var   Str: string[32];   StrLen: Byte absolute Str; //这个声明指定了变量StrLen起始地址与Str相同. //由于字符串的第0个位置保存了字符串的长度, 所以StrLen的值即字符串长度. begin   Str := 'abc';   Edit1.Text := IntToStr(StrLen); end; abstract//它允许你创建抽象的方法

java关键字详解

Java关键字及其作用 目录 Java关键字及其作用--- 1 一.     关键字总览:2 二.     详细解释--- 3 1.访问控制--- 3 1)私有的-- 3      private 2)受保护的-- 3      protected 3)公共的-- 3      public 2.类.方法和变量修饰符--- 3 1)声明抽象-- 3      abstract 2)类-- 4      class 3)继承.扩展-- 4      extends 4)最终.不可改变-- 4   

CSS3新增属性text-shadow详解及燃烧的字体实战开发

今天我们有很多程序员在给文本设置样式时,都感觉无从下手.一般有两种情况: 1) 不知道关于文本到底有哪些样式属性: 2) 即使借助开发工具的自动提醒,依然不清楚样式属性的具体意思,以及具体用法. 今天这篇文章,我将带领大家一起来领受CSS3在文本样式应用方面的超强能力.通过精彩的实例,来使大家重新认识CSS3文本样式,真心希望大家通过此篇文章,即使不能做到精通CSS3的文本样式的应用,也会做到熟练应用. 实例: 如何利用CSS3制作燃烧的字体? 以前,如果我们网页上想要显示一个燃烧着的文本,大家

objective C 内存管理及属性方法详解

oc为每个对象提供一个内部计数器,这个计数器跟踪对象的引用计数,当对象被创建或拷贝时,引用计数为1,每次保持对象时,调用retain接口,引用计数加1,如果不需要这个对象时调用release,引用计数减1,当对像的引用计数为0时,系统就会释放掉这块内存,释放对象调用dealloc 当对象包含其他对象时,就得在dealloc中自己释放他们 NSObject是IOS所有类的基类 有两个基本函数,alloc和dealloc alloc类似于C++的new,dealloc类似于delete 当对象的re

【C语言天天练(十四)】const关键字详解

const是一个C语言的关键字,它限定一个变量不允许被改变.使用const在一定程度上可以提高程序的安全性和可靠性,另外,了解const的作用,在看别人的代码时,对理解对方的程序有一定帮助. 1.const可以理解成是"只读变量"的限定词,从这里可以看出,const修饰的是变量,跟常量是不同的,常量是被编译器放在内存中的只读区域,当然也就不能够去修改它.而"只读变量"则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改.const就是用来限定一

“全栈2019”Java异常第九章:throws关键字详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异常第九章:throws关键字详解 下一章 "全栈2019"Java异常第十章:throw与throws区别详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Ja

C#关键字详解第二节

base:基类 在有些书中base的解释为表示父类,没错,base可以表示父类,但我更想理解成基类,因为更原始更具象,既 然是类,那么他就符合面向对象的设计规则和特点,我们知道面向对象的三个特点是封装,继承和多态!而 base就是对于多态最合理的定义,因为基类衍生出了其他类,而这里的衍生就是多态的体现,一般来说base在 派生类(子类)中访问重写的基类成员,当然基类访问只能在构造函数,实例方法或实例属性访问器中进行. 下面看例子 namespace base关键字 { class Program

java-this关键字详解

Java this关键字详解 this 关键字用来表示当前对象本身,或当前类的一个实例,通过 this 可以调用本对象的所有方法和属性.例如: public class Demo{ public int x = 10; public int y = 15; public void sum(){ // 通过 this 点取成员变量 int z = this.x + this.y; System.out.println("x + y = " + z); } public static vo