任務(wù)管理器(TaskManager)
任務(wù)管理
- 為什么需要任務(wù)管理
- 實(shí)現(xiàn)思路
- 部分邏輯代碼
- Task
- 延伸
為什么需要任務(wù)管理
在設(shè)計(jì)router的時(shí)候我們?cè)Mㄟ^(guò)類映射的方式將一些特殊的服務(wù)例如api請(qǐng)求,而在之后我發(fā)現(xiàn)因?yàn)閠ask任務(wù)的生命周期問(wèn)題,在model回調(diào)之前整個(gè)task都已經(jīng)被釋放了,所以我需要一個(gè)manager來(lái)負(fù)責(zé)管理這些任務(wù),包括了任務(wù)完成之后的釋放。
實(shí)現(xiàn)思路
我新建了一個(gè)TaskManager的類作為管理器,考慮到我們現(xiàn)在的業(yè)務(wù)大部分頁(yè)面的點(diǎn)擊事件都是在這里,在這里我先添加了一個(gè)ManagerDic的可變字典,大致的結(jié)構(gòu)是
{key : [TASK1,TASK2]} key對(duì)應(yīng)的就是約定的類名
之后我用了KVO來(lái)進(jìn)行管理,在HHTask這個(gè)類里添加了一個(gè)屬性completeTask 來(lái)做判斷 當(dāng)任務(wù)完成 將completeTask置成yes,然后 移除在TaskManager里面的任務(wù),移除觀察者。
部分邏輯代碼
首先判斷是否已經(jīng)有對(duì)應(yīng)的數(shù)組存在,task任務(wù)
完成以后remove掉自己的任務(wù)就好,如果還沒(méi)有任務(wù)就生成對(duì)應(yīng)任務(wù)數(shù)組。
+ (void)addTask:(id)task key:(NSString *)key{
HHTaskManager *manager = [HHTaskManager shared];
@synchronized (self) {
if (manager.managerDic[key]) {
NSMutableArray *taskArray = manager.managerDic[key];
[taskArray addObject:task];
}
else {
NSMutableArray *taskArray = [NSMutableArray array];
[taskArray addObject:task];
[manager.managerDic setObject:taskArray forKey:key];
}
[task addObserver:manager forKeyPath:@"completeTask" options:0 context:nil];
NSMethodSignature *sig= [[task class] instanceMethodSignatureForSelector:@selector(excuteTask)];
NSInvocation *invocation=[NSInvocation invocationWithMethodSignature:sig];
invocation.target = task;
invocation.selector = @selector(excuteTask);
[invocation invoke];
}
}
上面這一部分任務(wù)的執(zhí)行 其實(shí)可拓展性會(huì)比較強(qiáng) 如果是與UI有關(guān)系的任務(wù)可以放在主線程進(jìn)行,這里可以在初始化task的時(shí)候給他一個(gè)status的狀態(tài)來(lái)判斷。我們現(xiàn)在的做法是在我們的router解析完以后有一個(gè)規(guī)則依靠規(guī)則來(lái)判斷。
這里利用了KVO來(lái)檢測(cè)任務(wù)完成,完成以后移除任務(wù)和觀察者
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
HHTaskManager *manager = [HHTaskManager shared];
if (manager.managerDic[NSStringFromClass([object class])]) {
NSMutableArray *taskArray = manager.managerDic[NSStringFromClass([object class])];
[object removeObserver:manager forKeyPath:@"completeTask"];
[taskArray removeObject:object];
}
}
Task
typedef void (^TaskResult)(BOOL isSucceed, NSDictionary *userInfo);
@interface Task : NSObject
@property (nonatomic, assign) BOOL isNeedLogin;
@property (nonatomic, copy) TaskResult callback;
@property (nonatomic, strong)NSString *completeTask;
- (void)initWithparam:(NSDictionary *)param;
- (void)excuteTask;
//子類實(shí)現(xiàn)方法
- (void)excuteDetailTask;
對(duì)應(yīng)的task的設(shè)計(jì),起初想設(shè)立一定的規(guī)則模塊來(lái)完善登錄這個(gè)動(dòng)作,后來(lái)還是決定增加一個(gè)屬性來(lái)判斷是否需要登錄,考慮了登錄以后有回調(diào)的需求。 預(yù)留了一個(gè)callback給一些任務(wù)完成以后需要有特殊回調(diào)的需求。completeTask是表示任務(wù)是否完成。因?yàn)榭紤]到 有api請(qǐng)求的需要等到api返回以后才是真正的完成了任務(wù)。這是一個(gè)基類。然后可以看一下我的其他任務(wù)子類代碼。
@interface HHWapTask : Task
@property (nonatomic, strong)NSString *url;
@end
可以看到其實(shí)不同的task任務(wù)還會(huì)分解出不同的參數(shù),在- (void)initWithparam:(NSDictionary *)param;這個(gè)方法里將你所需要的參數(shù)進(jìn)行了分解。之后再執(zhí)行任務(wù)即可。
延伸
剛開(kāi)始我打算做的是一個(gè)任務(wù)的存儲(chǔ)和管理,之后考慮的是一些重復(fù)的任務(wù)之間因?yàn)閗ey 是相同的通過(guò)key我可以判斷是否直接取消這個(gè)任務(wù),在task里面可以加一個(gè)任務(wù)是否需要啟動(dòng)的開(kāi)關(guān),如果發(fā)現(xiàn)任務(wù)重復(fù)就設(shè)置為不開(kāi)啟,然后直接移除任務(wù)。