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;
}