环境
- Xcode Version 8.0 (8A218a)
- Objective-C
回顾MRC内存管理的黄金法则
- 自己生成的对象,自己持有 (alloc , new ,copy, mutalbleCopy )
- 不是自己生成的对象,也可以持有 (retain)
- 自己持有的对象不再需要时释放 (release)
- 非自己持有的对象不能释放
对整个项目设置是否使用ARC
PROJECT -> Build settings -> Apple LLVM 8.0 - Language - Objective C -> Objective-C Automatic Reference Counting 设置YES或者NO来开启或者关闭ARC
对项目里的单个或部分源文件设置是否使用ARC
PROJECT -> Build Phases -> Compile Sources 选中(可多选)需要设置的源文件,设置右侧的Compiler Flag
- 用-fno-objc-arc标记来禁用在ARC工程那些不支持ARC的文件的ARC
- 用-fobjc-arc标记启用非ARC工程中支持ARC的文件
SDK中ARC相关的宏定义,类和方法
// Marks methods and functions which cannot be used when compiling in automatic reference counting mode.
#if __has_feature(objc_arc)
#define NS_AUTOMATED_REFCOUNT_UNAVAILABLE __attribute__((unavailable("not available in automatic reference counting mode")))
#else
#define NS_AUTOMATED_REFCOUNT_UNAVAILABLE
#endif
/* OBJC_ARC_UNAVAILABLE: unavailable with -fobjc-arc */
#if !defined(OBJC_ARC_UNAVAILABLE)
# if __has_feature(objc_arc)
# define OBJC_ARC_UNAVAILABLE OBJC_UNAVAILABLE("not available in automatic reference counting mode")
# else
# define OBJC_ARC_UNAVAILABLE
# endif
#endif
/*********** Object Allocation / Deallocation *******/
FOUNDATION_EXPORT id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone * _Nullable zone) NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
FOUNDATION_EXPORT void NSDeallocateObject(id object) NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
FOUNDATION_EXPORT id NSCopyObject(id object, NSUInteger extraBytes, NSZone * _Nullable zone) NS_AUTOMATED_REFCOUNT_UNAVAILABLE NS_DEPRECATED(10_0, 10_8, 2_0, 6_0);
FOUNDATION_EXPORT BOOL NSShouldRetainWithZone(id anObject, NSZone * _Nullable requestedZone) NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
FOUNDATION_EXPORT void NSIncrementExtraRefCount(id object) NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
FOUNDATION_EXPORT BOOL NSDecrementExtraRefCountWasZero(id object) NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
FOUNDATION_EXPORT NSUInteger NSExtraRefCount(id object) NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
NS_AUTOMATED_REFCOUNT_UNAVAILABLE
@interface NSAutoreleasePool : NSObject
@autoreleasepool {
// Code, such as a loop that creates a large number of temporary objects.
}
@protocol NSObject
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
- (oneway void)release OBJC_ARC_UNAVAILABLE;
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
- (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
@interface NSObject <NSObject>
+ (id)copyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
+ (id)mutableCopyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
ARC中的修饰符
- __strong
1. __strong修饰符是id类型和对象类型默认的所有权修饰符。
2. 持有强引用的变量在超出其作用域时被废弃,随着强引用的失效,引用的对象会随之释放。
3. 无法解决 循环引用,会造成内存泄漏,既应当废弃的对象在超出其生存周期后继续存在。 - __weak
1. 弱引用,不能持有对象实例。
2. 当弱引用的对象被废弃,则此弱引用将自动失效且处于nil被赋值的状态(空弱引用)。通过检查附有__weak修饰符的变量是否为nil,可以判断被赋值的对象是否被废弃。
3. 适用于iOS5以上版本,在iOS4中可以使用__unsafe_unretained修饰符代替。 - __unsafe_unretained
1. 修饰符的变量不属于编译器的内存管理对象,是不安全的所有权修饰符。既不持有对象的强引用,又不持有对象的弱引用。 - __autoreleasing
1. ARC有效,且要使用autorelease时,可以通过将对象赋值给附加了__autoreleasing修饰符的变量。
2. 主要在 @autoreleasepool{ } 代码块中使用。
其中 strong,weak,autoreleasing 修饰符可以保证附有这些修饰符的自动变量初始化为nil。
属性@property中对应的修饰符
属性 | 修饰符 |
---|---|
assign | __unsafe_unretained |
copy | __strong (复制对象) |
retain | __strong |
strong | __strong |
__unsafe_unretained | __unsafe_unretained |
weak | __weak |
注意事项
- retain,release, autorelease,retainCount 禁用,@selector(release) 也不可以。编译器自动生成合适的dealloc,不能手动调用, 不能调用[super dealloc]。
- 属性访问器不能以new开头。
// Won't work:
@property NSString *newTitle;
- 在 ARC模式下,__strong是对象类型默认的修饰符。
- 再没有必要使用NSZone,他们已经被现代Objective-C runtime忽略。
- IBOutlet选择修饰符,如果该控件位于控件树的顶部,比如 UIViewController下的view,那就应该选择strong;而如果控件是viewcontroller中view的子视图使用weak。
- id类型和泛型指针void * 的转换。 1 . 修饰符 _bridge 安全性与赋值给 _unsafe_unretained 修饰符相近,甚至更低,管理不当,可能会因悬垂指针导致崩溃。2 . 修饰符 _bridge_retained 可以使要转换赋值的变量也持有所赋值的对象。3 . __bridge_transfer 被转换的变量所持有的对象在该变量被赋值给转换目标变量后随之释放。
void * p = 0;
id obj = [[NSObject alloc] init];
void * p = (__bridge_retained void *)obj;
id obj = (__bridge_transfer id)p;