在使用块时, 如果不仔细思考, 很容易出现"保留环" (retain cycle). 下面举个例子:
我们创建一个获取网络数据的类
TYLNetworkFetcher.h
#import <Foundation/Foundation.h>
typedef void (^TYLNetworkFetcherCompletionHandler) (NSData *data);
@interface TYLNetworkFetcher : NSObject
- (void)startWithCompletionHandler:(TYLNetworkFetcherCompletionHandler)completion;
@end
TYLNetworkFetcher.m
#import "TYLNetworkFetcher.h"
@interface TYLNetworkFetcher ()
@property (nonatomic, copy) TYLNetworkFetcherCompletionHandler completionHandler;
@property (nonatomic, copy) NSData *downloadData;
@end
@implementation TYLNetworkFetcher
- (void)startWithCompletionHandler:(TYLNetworkFetcherCompletionHandler)completion {
self.completionHandler = completion;
// start request
// set download data
// call request completed
}
- (void)p_requestCompleted {
if (_completionHandler) {
_completionHandler(_downloadData);
}
}
@end
我们在ViewController.m中使用它:
#import "ViewController.h"
#import "TYLNetworkFetcher.h"
@interface ViewController ()
@property (nonatomic, strong) TYLNetworkFetcher *networkFetcher;
@property (nonatomic, copy) NSData *fetchData;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_networkFetcher = [TYLNetworkFetcher new];
[_networkFetcher startWithCompletionHandler:^(NSData *data) {
_fetchData = data;
}];
}
接下来我们编译的时候, xcode 并没有提示我们会造成循环引用
我们分析一下引用关系 如下图:
![](https://img.haomeiwen.com/i4075144/4230eafc51110d11.png)
我们可以有如下三种方式去解决循环引用问题:
- _networkFetcher 实例变量不再被ViewController 持有
![](https://img.haomeiwen.com/i4075144/cfb6e37e0e531df1.png)
- 使得 _networkFetcher的属性 不再持有completionHandler
![](https://img.haomeiwen.com/i4075144/080c36b27c95cca2.png)
- 修改 将viewController 对 networkFetcher属性的引用, 改为weak
![](https://img.haomeiwen.com/i4075144/5adb62adf7bfa445.png)
推荐使用第2种方式
参考 (编写高质量iOS 与 OX 52 个有效方法)
网友评论