iOS基础

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;
}
上一篇下一篇

猜你喜欢

热点阅读