WeakSelf和StrongSelf傻傻分不清楚,记录一下
准备工作
SimulationRequest
- SimulationRequest.h
@interface SimulationRequest : NSObject
@property (nonatomic, strong) NSMutableDictionary *requestDic;
+ (instancetype)sharkRequest; //单例对象
+ (instancetype)request; //init对象
- (NSUInteger)simulationRequestCompletation:(void(^)(NSString *msg))completion;
@end
- SimulationRequest.m
static dispatch_queue_t _kqueue = nil;
static NSUInteger _idt = 0;
@implementation SimulationRequest
+ (instancetype)sharkRequest{
static SimulationRequest *_kRequest = nil;
static dispatch_once_t token;
dispatch_once(&token, ^{
_kRequest = [[SimulationRequest alloc] init];
});
return _kRequest;
}
- (instancetype)init{
self = [super init];
if (self) {
self.requestDic = [[NSMutableDictionary alloc] init];
}
return self;
}
+ (void)initialize{
if (_kqueue == nil) {
_kqueue = dispatch_queue_create("SimulationRequest.queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_set_specific(_kqueue, &_kqueue, &_kqueue, NULL);
}
}
+ (instancetype)request{
SimulationRequest *request = [[self alloc] init];
return request;
}
- (NSUInteger)simulationRequestCompletation:(void (^)(NSString * _Nonnull))completion{
// 这里其实是需要对idt进行加锁的,Demo中请求在主线程中进行,省略了加锁操作
_idt ++;
if (completion) {
[self.requestDic setObject:[completion copy] forKey:@(_idt)];
}
dispatch_async(_kqueue, ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1*NSEC_PER_SEC), dispatch_get_main_queue(), ^{
void(^t)(NSString *) = [self.requestDic objectForKey:@(_idt)];
if (t) {
t(@"hello!!");
[self.requestDic removeObjectForKey:@(_idt)];
}
});
});
return _idt;
}
@end
创建对象
- WeakStrongClass.m
@implementation WeakStrongClass
- (void)request{
[[SimulationRequest sharkRequest] simulationRequestCompletation:^(NSString * _Nonnull msg) {
NSLog(@"request finish!!");
[self logMsg];
}];
}
- (void)logMsg{
NSLog(@"%p logMsg", &self);
}
- (void)dealloc{
NSLog(@"%s", __func__);
}
@end
测试开始
测试一 单例Request
- 创建一个
WeakStrongClass
类型局部变量进行网络请求
void weakStrongTest1(void) {
WeakStrongClass *obj1 = [[WeakStrongClass alloc]init];
[obj1 request];
}
- 日志输出
Hello, World!
request finish!!
0x7ffeefbfe2f8 logMsg
-[WeakStrongClass dealloc]
结论
-
SimulationRequest
单例对象只通过block持有了obj1
,obj1
并没有持有SimulationRequest
的单例对象,没有形成循环引用,所以obj1
能够执行- logMsg
方法并在block执行完成之后销毁
测试二 局部变量Request
WeakStrongClass
的对象使用临时创建的SimulationRequest
对象进行请求
- WeakStrongClass.m
- (void)request2{
[[SimulationRequest request] simulationRequestCompletation:^(NSString * _Nonnull msg) {
NSLog(@"request finish!!");
[self logMsg];
}];
}
- test
void weakStrongTest2(void) {
WeakStrongClass *obj1 = [[WeakStrongClass alloc]init];
[obj1 request2];
}
- 日志输出
Hello, World!
request finish!!
0x7ffeefbfe2d8 logMsg
-[WeakStrongClass dealloc]
结论
SimulationRequest
局部变量并没有进行销毁,但是WeakStrongClass
对象执行- logMsg
方法并在block执行完成之后销毁
- 修改
weakStrongTest2
添加AutoRelease使SimulationRequest
对象能够销毁
void weakStrongTest2(void) {
@autoreleasepool {
WeakStrongClass *obj1 = [[WeakStrongClass alloc]init];
[obj1 request2];
}
}
- 日志输出
Hello, World!
request finish!!
0x7ffeefbfe2f8 logMsg
-[WeakStrongClass dealloc]
-[SimulationRequest dealloc]
测试三 持有Request
- SimulationRequest.h
@interface WeakStrongClass: NSObject
@property (nonatomic, strong) SimulationRequest *simRequest;
@end
- SimulationRequest.m
- (instancetype)init{
self = [super init];
if (self) {
self.simRequest = [SimulationRequest request];
}
return self;
}
- (void)request3{
[self.simRequest simulationRequestCompletation:^(NSString * _Nonnull msg) {
NSLog(@"request finish!!");
[self logMsg];
}];
}
- test
void weakStrongTest3(void) {
WeakStrongClass *obj1 = [[WeakStrongClass alloc]init];
[obj1 request3];
}
- 日志输出
Hello, World!
request finish!!
0x7ffeefbfe2d8 logMsg
-[WeakStrongClass dealloc]
结论
WeakStrongClass
对象进行了正常的销毁。虽然obj1
->request
->Dictionary
->obj1
行成了一个闭环,但是[self.requestDic removeObjectForKey:@(_idt)];
打破了循环,使得obj1
对象进行了释放
- 增加
autoreleasepool
void weakStrongTest3(void) {
@autoreleasepool {
WeakStrongClass *obj1 = [[WeakStrongClass alloc]init];
[obj1 request3];
}
}
- 日志输出
Hello, World!
request finish!!
0x7ffeefbfe2d8 logMsg
-[WeakStrongClass dealloc]
-[SimulationRequest dealloc]
测试四 字典不移除元素
假设SimulationRequest对失败的请求进行暂存,后续继续存储。但是WeakStrongClass已经不在关注请求情况
- 注释
SimulationRequest
的移除操作
dispatch_async(_kqueue, ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1*NSEC_PER_SEC), dispatch_get_main_queue(), ^{
reqCompletion reqHandler = [self.requestDic objectForKey:@(_idt)];
reqHandler(@"hello !");
//[self.requestDic removeObjectForKey:@(_idt)];
});
});
- 使用weakSelf
- (void)request4{
__weak typeof(self) weakSelf = self;
[self.simRequest simulationRequestCompletation:^(NSString * _Nonnull msg) {
NSLog(@"request finish!! *** %@",msg);
[weakSelf logMsg];
}];
}
- test
static WeakStrongClass *_kObj;
void weakStrongTest4(void) {
@autoreleasepool {
WeakStrongClass *obj1 = [[WeakStrongClass alloc]init];
[obj1 request4];
_kObj = obj1;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC), dispatch_get_global_queue(0, 0), ^{
_kObj = nil;
});
}
}
使用
WeakStrongClass *_kObj
来模拟viewController被展示,同时模拟2秒后退出当前页面
- 日志
Hello, World!
request finish!! *** hello !
0x7ffeefbfe2e8 logMsg
-[WeakStrongClass dealloc]
-[SimulationRequest dealloc]
结论
WeakStrongClass
现在可以正常释放,不受SimulationRequest
的影响
问题,何时使用strongSelf?
假设在block执行过程中,obj1对象被销毁怎样?这是就需要使用strongSelf了
- 模拟场景
- (void)request5{
__weak typeof(self) weakSelf = self;
[self.simRequest simulationRequestCompletation:^(NSString * _Nonnull msg) {
NSLog(@"request finish!! *** %@",msg);
[weakSelf logMsg];
sleep(3);
[weakSelf logMsg];
}];
}
- test
static WeakStrongClass *_kObj; // 和weakStrongTest4上的‘_kObj’只能存在一个
void weakStrongTest5(void) {
@autoreleasepool {
WeakStrongClass *obj1 = [[WeakStrongClass alloc]init];
[obj1 request5];
_kObj = obj1;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC), dispatch_get_global_queue(0, 0), ^{
_kObj = nil;
});
}
}
模拟viewController被展示,同时模拟2秒后退出当前页面,但是request5中的回调有耗时操作
- 日志输出
Hello, World!
request finish!! *** hello !
0x7ffeefbfe2d8 logMsg
-[WeakStrongClass dealloc]
-[SimulationRequest dealloc]
结论
logMsg只执行了一次,第二次执行时,WeakStrongClass
被global线程释放导致weakSelf = nil,第二次logMsg没有执行
- 增加StrongSelf
- (void)request5{
__weak typeof(self) weakSelf = self;
[self.simRequest simulationRequestCompletation:^(NSString * _Nonnull msg) {
NSLog(@"request finish!! *** %@",msg);
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf logMsg];
sleep(3);
[strongSelf logMsg];
}];
}
- 日志输出
Hello, World!
request finish!! *** hello !
0x7ffeefbfe2d8 logMsg
0x7ffeefbfe2d8 logMsg
-[WeakStrongClass dealloc]
-[SimulationRequest dealloc]
结论
logMsg执行了两次,符合预期效果
注意
如果 __strong typeof(weakSelf) strongSelf = weakSelf;执行之前,weakSelf已经是nil,logMsg不执行
- 修改代码顺序
- (void)request5{
__weak typeof(self) weakSelf = self;
[self.simRequest simulationRequestCompletation:^(NSString * _Nonnull msg) {
NSLog(@"request finish!! *** %@",msg);
[weakSelf logMsg];
NSLog(@"will strongSelf");
sleep(3);
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf logMsg];
}];
}
- 日志输出
Hello, World!
request finish!! *** hello !
0x7ffeefbfe2d8 logMsg
will strongSelf
-[WeakStrongClass dealloc]
-[SimulationRequest dealloc]