iOS Block的内存管理

1. Block实际上是指向结构体的指针,编译器会将内部的代码生成对应的函数

2. Block内部使用了外部的变量, 内部是否能修改外部的变量,取决于外部变量是怎么给Block传值的:

  1>如果传的指针,就可以改;

  2>如果传的只是变量的数值,则不可以改.

3. Block的内存管理:

  1>默认情况下,Block的内存在栈中,它不会对所引用的对象做任何操作

    Person *p = [[Person alloc]init];

    p.age = 20;

    void (^block)() = ^{

        NSLog(@"--block-%d",p.age);

    };

    block();

    [p release];

打印: --block-20

    人被释放了

  2>对Block做一次copy操作,block的内存就会做一次retain操作:

    a>非ARC,如果所引用的对象,使用 __block修饰,就不会做retain操作

    b>ARC,如果所引用的对象,使用 __weak __unsafe_unretained 修饰,就不会做retain操作

    Person *p = [[Person alloc]init];

    p.age = 20;

    void (^block)() = ^{

        NSLog(@"--block-%d",p.age);

    };

    Block_copy(block);

    [p release]; //执行到改行,人不会释放, 修改代码:__block Person *p = [[Person alloc]init];就可以释放

  3>非ARC中,一个类的Block属性,如果想做到这个类的对象存在,Block就存在.则这个Block属性不能用assign,必须用copy

      a>因为Block的内存是在栈中,随时可能会被释放

    b>用copy的花,Block的内存在堆中,它的释放由程序员控制

    c>在类的- (void)dealloc方法中, 加上 Block_release(block块对象名);

           d>在init方法中,Block引用外部变量时,要注意避免循环retain

#pragma mark - person.h

@interface Person : NSObject

@property (assign,nonatomic) NSInteger age;

@property (copy,nonatomic) void (^myBlock)();

@end

#pragma mark - person.m

#import "Person.h"

 @implementation Person

- (void)dealloc

{

    NSLog(@"人被释放了");

    Block_release(self.myBlock);

    [super dealloc];

}

@end

#pragma mark - person.m

- (id)init

{

    if (self = [super init]) {

        self.myBlock = ^{

            NSLog(@"---%d",self.age); // 因为myBlock属性是copy类型,所以会对内部的self做retain

        };

    }

    return self;

}

#pragma mark - mainViewController.m

Person *p = [[Person alloc]init]; 

[p release]; //仅看这2行代码,看不出有内存泄露,内存泄露的问题是出在init方法内部

正确的写法:

#pragma mark - person.m

- (id)init

{

    if (self = [super init]) {

     __block typeof (self) p = self;

        self.myBlock = ^{

            NSLog(@"---%d",p.age); 

        };

    }

    return self;

}

    

原文地址:https://www.cnblogs.com/oumygade/p/4280779.html