OC 中关于成员变量和属性的区别, 在阅读下面内容之前请自行 google.
工程目录如下
示例较简单, ViewController 直接打开 CoreViewController.
完整例子下载, 请戳这里!
Person.h
#import <Foundation/Foundation.h>
typedef void(^PlayFunction)(int x);
@interface Person : NSObject
@property (strong, nonatomic) PlayFunction playBlock;
@end
Person.m
没有任何实现.
ViewController.m
#import "ViewController.h"
#import "CoreViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
CoreViewController *page = [CoreViewController new];
[self.navigationController pushViewController:page animated:YES];
}
@end
#import "CoreViewController.h"
#import "Person.h"
@interface CoreViewController ()
{
BOOL isKill;
}
@property (strong, nonatomic) Person *person;
@end
@implementation CoreViewController
- (void)dealloc
{
NSLog(@"CoreViewController dealloc");
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
_person = [[Person alloc] init];
_person.playBlock = ^ void (int x) {
isKill = NO;
};
}
@end
编译运行, 在 CoreViewController 返回的时候, 我们发现其 dealloc 方法并没有被调用.
接下来, 我们注释掉 playBlock 里面的这句
isKill = NO;
再编译运行, 发现 dealloc 方法被调用了.
也就是说, 原因在于 isKill 这个实例变量上面.
Person 是 CoreViewController 的强引用, 而 Person 的 block 属性对 CoreViewController也是强引用.
那么, 大家会说了, 修改 Person.h
#import <Foundation/Foundation.h>
typedef void(^PlayFunction)(int x);
@interface Person : NSObject
@property (copy, nonatomic) PlayFunction playBlock;
@end
发现还是不行.将 copy 改为 weak 吧, 没错, 这样的确可以.
但是, 你会看到编译器不高兴了.
看来这样不妥.
可能你会说, 在 ViewController 中将 person 改为 weak,
@property (weak, nonatomic) Person *person;
的确可以这么解决不释放的问题, 但是也有警告
那我们再换一种方式,
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
_person = [[Person alloc] init];
CoreViewController __weak *weakSelf = self;
_person.playBlock = ^ void (int x) {
CoreViewController __strong *strongSelf = weakSelf;
strongSelf->isKill = NO;
};
}
完美解决.
这里啰嗦一下, 千万不要使用 weakSelf 访问实例变量, 否则编译报错.
推荐阅读:
到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf