前言: 对于代理模式 的应用大家应该都很熟悉。比如: 发起一个网络请求对象 requester , requsester 的代理 设置成 某个特定的 controller ,如果 请求成功返回数据 controller 刷新页面 。如果请求失败又返回其他的 等等。而在 代理模式中 requseter 经常判断 它有没有设置代理 其次它的代理是否响应代理的方法。 因为有很多代理方法 是optional 的 可以实现可以不实现 。比如下面的实现:
if ([_delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)]) {
[_delegate networkFetcher:self didReceiveData:[NSData data]];
}
因如果不判断的话,而controller 又没有写这个方法就会造成崩溃。 但是比如 有这样一个场景 我们需要频繁的调用 代理方法
比如 更新的进度等等 频繁的判断 代理是否响应某个方法 本身就是就显得多余和耗费性能。我们可以将 方法响应能力缓存起来 。
而在iOS中 最佳的途径是 使用 bitfield 数据类型。这是一项C语言的特性。
解决方案:
构建类EOCNetworkFetcher:
#import <Foundation/Foundation.h>
@protocol EOCNetworkFetcherDelegate;
@interface EOCNetworkFetcher : NSObject
struct delegateFlags{
unsigned int didReceiveData:1;
unsigned int didFailWithError:1;
unsigned int didUpdateProgressTo:1;
};
/**
代理对象 不需要时 会自动清空
*/
@property (nonatomic,weak)id<EOCNetworkFetcherDelegate>delegate;
@property (nonatomic,assign)struct delegateFlags flag;
/**
开始 获取网络数据
*/
- (void)startFetchNetworkData;
/**
开始多次的频繁的更新进度
*/
- (void)startProgress;
/**
代理对象 不需要时 不会自动清空 我们要验证一下
*/
@property (nonatomic,unsafe_unretained)id<EOCNetworkFetcherDelegate>unretainDelegate;
@end
/**
在 协议方法中我们应该把发起委托的实例也一并传入方法中
这样 delegate 对象在实现相关方法是能根据传入的实例分别执行不同的代码了
apple 里很多的协议也是这样写的
*/
@protocol EOCNetworkFetcherDelegate <NSObject>
@optional
- (void)networkFetcher:(EOCNetworkFetcher *)fetcher
didReceiveData:(NSData *)data;
- (void)networkFetcher:(EOCNetworkFetcher *)fetcher
didFailureWithError:(NSError *)error;
- (void)networkFetcher:(EOCNetworkFetcher *)fetcher
didUpdateProgressTo:(float )progress;
@end
#import "EOCNetworkFetcher.h"
@implementation EOCNetworkFetcher
/**
开始 获取网络数据
*/
- (void)startFetchNetworkData
{
NSLog(@"start fetch network data");
if ([_delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)]) {
[_delegate networkFetcher:self didReceiveData:[NSData data]];
}
if ([_unretainDelegate respondsToSelector:@selector(networkFetcher:didReceiveData:)]) {
[_unretainDelegate networkFetcher:self didReceiveData:[NSData data]];
}
}
/**
开始多次的频繁的更新进度
*/
- (void)startProgress
{
if (_flag.didUpdateProgressTo) {
[_delegate networkFetcher:self didUpdateProgressTo:2];
}
/*
会造成崩溃 因为如果并没有写这个 而如果我们的符号位 判断 比 判断选择子要快很多
[_delegate networkFetcher:self didFailureWithError:nil];
*/
}
- (void)setDelegate:(id<EOCNetworkFetcherDelegate>)delegate
{
_delegate=delegate;
_flag.didReceiveData=[delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)];
_flag.didUpdateProgressTo=[delegate respondsToSelector:@selector(networkFetcher:didUpdateProgressTo:)];
_flag.didFailWithError=[delegate respondsToSelector:@selector(networkFetcher:didFailureWithError:)];
}
@end
第二步: 构建代理类
#import <Foundation/Foundation.h>
#import "EOCNetworkFetcher.h"
@interface EOCDataModel : NSObject<EOCNetworkFetcherDelegate>
/**
数据模型的name
*/
@property (nonatomic,strong)NSString *dataModelName;
- (instancetype)initWithName:(NSString *)name;
@end
#import "EOCDataModel.h"
@implementation EOCDataModel
- (instancetype)initWithName:(NSString *)name
{
if (self=[super init]) {
_dataModelName=name;
}
return self;
}
- (instancetype)init
{
return [self initWithName:@"hello_de_long"];
}
- (void)networkFetcher:(EOCNetworkFetcher *)fetcher didReceiveData:(NSData *)data
{
NSLog(@"%@ --- handle data",_dataModelName);
}
- (void)networkFetcher:(EOCNetworkFetcher *)fetcher didUpdateProgressTo:(float)progress
{
NSLog(@"prgogress update flag is %d",fetcher.flag.didUpdateProgressTo);
}
- (void)dealloc
{
NSLog(@"%@ dealloc ",_dataModelName);
}
期间 我们
如果代理的调用非常频繁,比如更新进度 那么我们可以优化成
设置bit-field 这样来不用频繁检测是否响应某个方法带来的消耗