监听AFNetworking的AFNetworkActivityIndicatorManager类activityCount属性,用单例一句话实现网络请求加载框

本文介绍了一种在iOS应用中统一处理网络请求加载指示的方法,避免了在每个页面请求前后手动添加MBProgressHUD的繁琐操作。通过自定义单例View,实现了更灵活的加载效果控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相信不少人给网络请求添加加载框的Loading效果时都用过MBProgressHUD,但每个页面都在请求前写一个MBProgressHUD show,请求完了再dismiss,着实有些麻烦.

有没有一种思路能统一在网络请求类里写上一个加载框,每个页面的请求就不用加上MBProgressHUD呢?//个别不需要加载框的页面单独处理,其余的都展示加载框呢?

答案是有:

在网络加载统一请求方法里,在post之前直接调用:

[MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].keyWindow animated:YES];

请求结果出来(无论成功或是超时失败)的回调中:

  [MBProgressHUD hideHUDForView:[UIApplication sharedApplication].keyWindow animated:YES];

 

但这样做有一点不好,就是每个网络请求都有加载框,你无法单独对某个特定的网络请求做单独处理.因为我们在某个特定页面即便在网络请求前设置了:MBProgressHUD hide,但最终进入网络请求统一方法中仍然会MBProgressHUD show.因为MBProgressHUD

并没有提供enableProgress属性.所以并不能在需要加载框的时候设置YES,或者不需要加载框的时候设置NO.当然,我们可以更改它的源代码,这样是行得通的.

 

综合上面的几点原因,不改MBProgressHUD源码又难以实现需求,改了又怕对后期更新和其它用到MBProgressHUD的页面产生影响.我们可以试着用自己的方式去实现.MBProgressHUD实际上就是一个单例View.我们完全可以自己定义个单例View,这个View可以像MBProgressHUD一样简洁通用,也可以定义的像美团加载页面小人儿跑步那种花里胡哨的效果.

 

//.h文件
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface LoadingIndicatorManager : UIView
@property (nonatomic, assign) BOOL disableIndicator;//根据传参设置是否启用本次请求的indicator功能

+(instancetype)sharedIndicator;

-(void)destructInstance;

@end

NS_ASSUME_NONNULL_END

//.m文件

#import "LoadingIndicatorManager.h"
#import <AFNetworking.h>
#import <AFNetworkActivityIndicatorManager.h>
#import <objc/runtime.h>
@interface LoadingIndicatorManager()

@property (nonatomic, strong) UIActivityIndicatorView *indicator;

@end
@implementation LoadingIndicatorManager
static id instance = nil;
static dispatch_once_t onceToken = 0;
+(instancetype)sharedIndicator{
    
    if(!instance) {
        
        
        dispatch_once(&onceToken, ^{
            
            instance = [[super allocWithZone:NULL]init];
            
        });
        
        
    }
    
    return instance;
    
    
}

-(instancetype)initWithFrame:(CGRect)frame{
    if(self = [super initWithFrame:frame]){
        
        instance = [self customInitMethod];
    }
    
    return instance;
}
-(instancetype)init{
    
    if(self = [super init]){
        //        instance = [self customInitMethod];
    }
    
    return instance;
}
+(instancetype)alloc{
    
    return [LoadingIndicatorManager sharedIndicator];
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    
    return [LoadingIndicatorManager sharedIndicator];
}







-(id)copyWithZone:(NSZone *)zone{
    
    return instance;
    
}
-(id)copy{
    
    return instance;
    
}
-(id)mutableCopy{
    
    return instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone{
    
    return instance;
    
}













#pragma mark - Private
-(instancetype)customInitMethod{
    
    
//    self.disableIndicator = ![AFNetworkActivityIndicatorManager sharedManager].isEnabled;//根据AFN的indicator是否打开来统一设置
    
    self.backgroundColor = [UIColor blackColor];
    self.alpha = 0.4;
    
    
    self.indicator = ({
        
        UIActivityIndicatorView *indicator  = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
        
        indicator.hidesWhenStopped = YES;
        
        indicator.frame = CGRectMake(SCREENWIDTH/2-40, SCREENHEIGHT/2-40, 80, 80);
        
        
        [self addSubview:indicator];
        
        indicator;
    });
    
    
    

    
    
    //AFN为activityCount增加了KVO兼容
    //监听AFNetworkActivityIndicatorManagerd的activityCount,根据count来处理indicator
    [[AFNetworkActivityIndicatorManager sharedManager] addObserver:self forKeyPath:@"activityCount" options:NSKeyValueObservingOptionNew context:nil];
    
    return self;
    
    
}

/*
 
 移除以及添加indicatorView的时候,需要根据当前indicatorView的状态判断,已经在显示时就不再添加
 
 **/

//接收到AFN网络状态的通知,根据网络状态进行相应的处理
-(void)networkRequestDidStart:(NSNotification *)notification {
    
    
//    UIWindow *keyWin = [UIApplication sharedApplication].keyWindow;
//
//    [keyWin addSubview:self];
//    self.frame = keyWin.bounds;
//    self.alpha = 0.4;
//    [self.indicator startAnimating];
    
    if(self.disableIndicator){
       
    }else{
        UIWindow *keyWin = [UIApplication sharedApplication].keyWindow;
        
        [keyWin addSubview:self];
        self.alpha = 0.4;
        self.frame = keyWin.bounds;
        [self.indicator startAnimating];
        
    }
    
}

- (void)networkRequestDidFinish:(NSNotification *)notification {
    
//    [self performSelector:@selector(removeIndicator) withObject:nil afterDelay:4];
    
    if(self.disableIndicator){
        
      
    }else{
        
        [self.indicator stopAnimating];
        
        [self removeIndicator];
    }
    
}


+(void)removeIndicator{
    
    [[LoadingIndicatorManager sharedIndicator]removeIndicator];
    
}
-(void)removeIndicator{
    
    [UIView animateWithDuration:0.5 animations:^{
        self.alpha = 0;
        
    }completion:^(BOOL finished) {
        [self.indicator stopAnimating];
        [self removeFromSuperview];
        
    }];
    
}

//监听到AFNetworkActivityIndicatorManager的activityCount属性值,根据该值是否为0控制indicatorView的显示情况
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    if([keyPath isEqualToString:@"activityCount"]){
        
        
        NSLog(@"加载框------%@",change[@"new"]);
        NSInteger activeCount = [change[@"new"]integerValue];
        if(activeCount>0){
            
            if(_disableIndicator){
                
                
            }else{
                
                UIWindow *keyWin = [UIApplication sharedApplication].keyWindow;
                
                [keyWin addSubview:self];
                self.frame = keyWin.bounds;
                self.alpha = 0.4;
                
                [self.indicator startAnimating];
                
            }
           
            
        }else{
            
            
            [self removeIndicator];
            
        }
    }
    
}



#pragma =====单例的销毁&下一次重建单例========
-(void)destructInstance{
    //必要时销毁单例,重置onceToken为0
    instance = nil;
    onceToken = 0;
}
- (void)dealloc {
    
    NSLog(@"%sIndicator单例对象被释放",__func__);
    [[AFNetworkActivityIndicatorManager sharedManager] removeObserver:self forKeyPath:@"activityCount"];
    
//    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
}

@end

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值