背景
最近碰到一个需求,做视频播放的时候要求监控网络状态,若网络状态改变,比如没网到有网,自动刷新视频详情文案。
于是我就在视频播放VC里面的viewDidLoad方法里面加入了这一段代码
- (void)monitorNetWorkStart
{
// 1.获得网络监控的管理者
AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
// 2.设置网络状态改变后的处理
[mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
// 当网络状态改变了, 就会调用这个block
switch(status) {
case AFNetworkReachabilityStatusUnknown:// 未知网络
break;
case AFNetworkReachabilityStatusNotReachable:// 没有网络(断网)
break;
case AFNetworkReachabilityStatusReachableViaWWAN:// 手机自带网络
[self loadVideoDeatailDefault]; // 请求数据刷新界面
break;
case AFNetworkReachabilityStatusReachableViaWiFi:// WIFI
[self loadVideoDeatailDefault];
break;
}
}];
// 3.开始监控
[mgr startMonitoring];
}
本以为问题解决了,然而又出现了新的问题,退出视频页的时候,视频还在继续播放!!!
这妥妥的VC没释放啊,因为之前从没实战过,所以查了一些资料找到了问题所在
坑是怎么出现的
AFNetworkReachabilityManager是一个单例,它持有了一个block属性,单例在进程死掉之前不会被释放,所以block的引用计数一直为1。
在block中调用了 视频播放VC 的方法,所以block持有了 视频播放VC ,视频播放VC引用计数+1,并且因为block不会被释放,所以 视频播放VC 也不会被释放。
在block中调用某个对象的方法,或者用了某个对象的属性,block就会持有该对象,而不是该对象的方法或属性
怎么解决
- (void)monitorNetWorkStart
{
// 1.获得网络监控的管理者
AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
// 2.设置网络状态改变后的处理
__weak __typeof__(self) weakSelf = self;
[mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
__typeof__(self) self = weakSelf;
if (self.navigationController.topViewController != self) {
return;
}
// 当网络状态改变了, 就会调用这个block
switch(status) {
case AFNetworkReachabilityStatusUnknown:// 未知网络
break;
case AFNetworkReachabilityStatusNotReachable:// 没有网络(断网)
break;
case AFNetworkReachabilityStatusReachableViaWWAN:// 手机自带网络
[self loadVideoDeatailDefault]; // 请求数据刷新界面
break;
case AFNetworkReachabilityStatusReachableViaWiFi:// WIFI
[self loadVideoDeatailDefault];
break;
}
}];
// 3.开始监控
[mgr startMonitoring];
}
加__weak __修饰self可以使block不持有 视频播放VC,VC该释放的时候就释放
typeof(self) self = weakSelf; 这句可以防止 在执行block时self被释放造成crash
后记
小白一枚,如果哪里说的不对,请指正~