任務(wù)管理器(TaskManager)
任務(wù)管理
- 為什么需要任務(wù)管理
- 實現(xiàn)思路
- 部分邏輯代碼
- Task
- 延伸
為什么需要任務(wù)管理
在設(shè)計router的時候我們曾希望通過類映射的方式將一些特殊的服務(wù)例如api請求遗菠,而在之后我發(fā)現(xiàn)因為task任務(wù)的生命周期問題,在model回調(diào)之前整個task都已經(jīng)被釋放了盐杂,所以我需要一個manager來負責(zé)管理這些任務(wù)驳棱,包括了任務(wù)完成之后的釋放批什。
實現(xiàn)思路
我新建了一個TaskManager的類作為管理器,考慮到我們現(xiàn)在的業(yè)務(wù)大部分頁面的點擊事件都是在這里社搅,在這里我先添加了一個ManagerDic的可變字典驻债,大致的結(jié)構(gòu)是
{key : [TASK1,TASK2]} key對應(yīng)的就是約定的類名
之后我用了KVO來進行管理,在HHTask這個類里添加了一個屬性completeTask 來做判斷 當(dāng)任務(wù)完成 將completeTask置成yes形葬,然后 移除在TaskManager里面的任務(wù)合呐,移除觀察者。
部分邏輯代碼
首先判斷是否已經(jīng)有對應(yīng)的數(shù)組存在笙以,task任務(wù)
完成以后remove掉自己的任務(wù)就好淌实,如果還沒有任務(wù)就生成對應(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í)行 其實可拓展性會比較強 如果是與UI有關(guān)系的任務(wù)可以放在主線程進行,這里可以在初始化task的時候給他一個status的狀態(tài)來判斷翩伪。我們現(xiàn)在的做法是在我們的router解析完以后有一個規(guī)則依靠規(guī)則來判斷微猖。
這里利用了KVO來檢測任務(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;
//子類實現(xiàn)方法
- (void)excuteDetailTask;
對應(yīng)的task的設(shè)計缘屹,起初想設(shè)立一定的規(guī)則模塊來完善登錄這個動作凛剥,后來還是決定增加一個屬性來判斷是否需要登錄,考慮了登錄以后有回調(diào)的需求轻姿。 預(yù)留了一個callback給一些任務(wù)完成以后需要有特殊回調(diào)的需求犁珠。completeTask是表示任務(wù)是否完成。因為考慮到 有api請求的需要等到api返回以后才是真正的完成了任務(wù)互亮。這是一個基類犁享。然后可以看一下我的其他任務(wù)子類代碼。
@interface HHWapTask : Task
@property (nonatomic, strong)NSString *url;
@end
可以看到其實不同的task任務(wù)還會分解出不同的參數(shù)豹休,在- (void)initWithparam:(NSDictionary *)param;這個方法里將你所需要的參數(shù)進行了分解炊昆。之后再執(zhí)行任務(wù)即可。
延伸
剛開始我打算做的是一個任務(wù)的存儲和管理威根,之后考慮的是一些重復(fù)的任務(wù)之間因為key 是相同的通過key我可以判斷是否直接取消這個任務(wù)凤巨,在task里面可以加一個任務(wù)是否需要啟動的開關(guān),如果發(fā)現(xiàn)任務(wù)重復(fù)就設(shè)置為不開啟洛搀,然后直接移除任務(wù)敢茁。