iOS:重温MRC
2020-08-12 本文已影响0人
春暖花已开
由于现在编译器默认是ARC,所以在测试的时候,把
Build Settings
里的CLANG_ENABLE_OBJC_ARC
设为NO
。或者,不修改上面的设置,在Compile Sources
里对应的编译文件设为-fno-objc-arc
,表示对应的实现文件以MRC的方式编译。
MZAnimal
//MZAnimal.h
#import <Foundation/Foundation.h>
@interface MZCat : NSObject
- (void)run;
@end
@interface MZDog : NSObject
- (void)run;
@end
//MZAnimal.m
#import "MZAnimal.h"
@implementation MZCat
- (void)run {
NSLog(@"%s", __func__);
}
- (void)dealloc {
[super dealloc];
NSLog(@"%s", __func__);
}
@end
@implementation MZDog
- (void)run {
NSLog(@"%s", __func__);
}
- (void)dealloc {
[super dealloc];
NSLog(@"%s", __func__);
}
@end
MZPerson
//MZPerson.h
#import <Foundation/Foundation.h>
#import "MZAnimal.h"
@interface MZPerson : NSObject {
//需要自己手动生成set/get方法
MZDog *_dog;
}
///在MRC里,retain关键字表示会由编译器帮我们生成ivar和set/get方法,生成的set方法里自带内存管理
@property (nonatomic, retain) MZCat *cat;
- (void)setDog:(MZDog *)dog;
- (MZDog *)dog;
+ (instancetype)person;
@end
//MZPerson.m
#import "MZPerson.h"
@implementation MZPerson
+ (instancetype)person {
//autorelease表示由系统管理,无需手动调用release
return [[[MZPerson alloc] init] autorelease];
}
- (void)setDog:(MZDog *)dog {
//这里必须要判断_dog != dog
if (_dog != dog) {
//释放旧对象
[_dog release];
//持有新对象
_dog = [dog retain];
}
}
- (MZDog *)dog {
return _dog;
}
- (void)dealloc {
//在释放dealloc的时候,要手动置为nil
[self setDog:nil];
self.cat = nil;
/**
[self setDog:nil]; 相当于
[_dog release];
_dog = nil;
*/
NSLog(@"%s", __func__);
[super dealloc];
}
@end
main
#import <Foundation/Foundation.h>
#import "MZPerson.h"
#import "MZAnimal.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
/**
MRC内存管理规则:
1. 自己生成的对象,自己持有.
- 通过alloc/new/copy/mutableCopy等方法创建的对象,都需要release.
2. 不是(非)自己生成的对象,自己也能持有:NSMutableArray *array = [NSMutableArray array];
3. 无法释放非自己持有的对象.
*/
MZPerson *person = [[MZPerson alloc] init];
MZDog *dog = [[MZDog alloc] init];
MZCat *cat = [[MZCat alloc] init];
[person setDog:dog];
person.cat = cat;
[person.dog run];
[person release];
[dog release];
[cat release];
/**
因为`+ (instancetype)person`的方法里调用了autorelease,不用手动调用release
如果调用 `[xm release];` 则会崩溃.原因是:
xm没有进行retain操作而进行release操作,然后autoreleasePool也会对其进行一次release操作,导致了奔溃.
*/
MZPerson *xm = [MZPerson person];
/**
类似于以下这种格式的,都是不需要手动release的
[NSMutableArray array];
[NSString stringWithFormat:@"Lily"];
`[NSMutableArray array];` 底层实现类似于:
```
+ (id)object {
//自己持有对象
id obj = [[NSObject alloc]init];
[obj autorelease];
//取得的对象存在,但自己不持有对象
return obj;
}
```
*/
NSMutableArray *array = [NSMutableArray array];
NSString *name = [NSString stringWithFormat:@"Lily"];
}
return 0;
}