如今模塊間不少用事件總線解耦。以往的事件總線都是單向傳遞數據, 返回數據只能異步回調; 有時我想發送一個數據到某模塊處理完返回結果才進行下一步驟, 若是一個地方出現屢次請求數據,異步嵌套代碼可讀性很低; 想用 'performSelector' 來解耦函數調用,但有參數限制, 而後發現NSInvocation更增強大,因此選用NSInvocation來實現事件總線。git
區別 | NSInvocation | performSelector | NSNotification |
---|---|---|---|
參數 | 可多參數 | 限制參數數量 | 用userInfo傳入參數 |
返回結果 | 有, 同步 | 有, 同步 | 單向傳遞, 無 |
調用耗時 | 0.006ms | 0.005ms | |
返回結果耗時 | 0.007ms | 0.003ms |
- 支持多參數傳遞,同步返回結果,耗時與直接調用該方法相差無幾
- 支持訂閱對象方法和類方法
- 無需手動註銷訂閱
// 在'DVEventBusDefine.h' 或者 'PCH'文件 自定義我的喜愛事件格式
#define kEVENT(event) static NSString *const kEVENT_##event = @"kEVENT_"#event;
#define kEVENT_MODULE(module,event) kEVENT(module##_##event)
#define kEVENT_GLOBAL_MODULE(module,event) kEVENT(GLOBAL_##module##_##event)
#define kEVENT_SERVICE_MODULE(module,event) kEVENT(SERVICE_##module##_##event)
#define kEVENT_DAO_MODULE(module,event) kEVENT(DAO_##module##_##event)
#define kEVENT_VM_MODULE(module,event) kEVENT(VM_##module##_##event)
// 建立 'DemoEvent.h' 自定義事件
kEVENT(DEMO) // 等於 kEVENT_DEMO
kEVENT_MODULE(DEMO, GET_DATA) // 等於 kEVENT_DEMO_GET_DATA
kEVENT_SERVICE_MODULE(DEMO, GET_DATA) // 等於 kEVENT_SERVICE_DEMO_GET_DATA
kEVENT_DAO_MODULE(DEMO, GET_DATA) // 等於 kEVENT_DAO_DEMO_GET_DATA
複製代碼
@interface DemoService() <DVEventBusClassDelegate> // 繼承 'DVEventBusClassDelegate'
@end
@implementation DemoService
/**
類事件 綁定 類方法
實現 'DVEventBusClassDelegate' 的 'event_classMethod_map' 方法
*/
+ (NSDictionary<NSString *,NSString *> *)event_classMethod_map {
return @{
kEVENT_SERVICE_DEMO_ADD : _sel(@selector(addWithA:b:)),
kEVENT_SERVICE_DEMO_GET_STRING : _sel(@selector(getString)),
kEVENT_SERVICE_DEMO_GET_OBJECT : _sel(@selector(getObject)),
kEVENT_SERVICE_DEMO_LOGIN : _sel(@selector(loginWithUserName:password:success:)),
kEVENT_SERVICE_DEMO_MUTIL_METHOD : _sel(@selector(mutilMethod1)) // 一個事件綁定多個方法, 順序執行
._sel(@selector(mutilMethod2))
._sel(@selector(mutilMethod3))
};
}
/*
傳入數字類型必須是'NSNumber'類型,返回數字類型也是'NSNumber'類型
*/
+ (NSNumber *)addWithA:(NSNumber *)a b:(NSNumber *)b {
int ret = [a intValue] + [b intValue];
return @(ret);
}
+ (NSString *)getString {
return @"Hello world";
}
+ (UserModel *)getObject {
UserModel *model = [[UserModel alloc] init];
model.userName = @"David";
model.password = @"123456";
return model;
}
+ (void)loginWithUserName:(NSString *)userName password:(NSString *)password success:(void(^)(BOOL status))success {
NSLog(@"[DemoService LOG]: 登陸成功, userName-> %@, password-> %@", userName, password);
success(YES);
}
+ (void)mutilMethod1 {
NSLog(@"[DemoService LOG]: 觸發方法1");
}
+ (void)mutilMethod2 {
NSLog(@"[DemoService LOG]: 觸發方法2");
}
+ (void)mutilMethod3 {
NSLog(@"[DemoService LOG]: 觸發方法3");
}
@end
複製代碼
// 用這個方法註冊, 類必須繼承'DVEventBusClassDelegate' 和 實現'event_classMethod_map'
[DVEventSubscriber registerClassEvents:[DemoService class]];
複製代碼
[DVEventSubscriber addClasslEvent:kEVENT_SERVICE_DEMO_LOGIN subscriber:[DemoService class] action:@selector(loginWithUserName:password:success:)];
[DVEventSubscriber addClasslEvent:kEVENT_SERVICE_DEMO_ADD subscriber:[DemoService class] action:@selector(addWithA:b:)];
[DVEventSubscriber addClasslEvent:kEVENT_SERVICE_DEMO_GET_STRING subscriber:[DemoService class] action:@selector(getString)];
[DVEventSubscriber addClasslEvent:kEVENT_SERVICE_DEMO_GET_OBJECT subscriber:[DemoService class] action:@selector(getObject)];
[DVEventSubscriber addClasslEvent:kEVENT_SERVICE_DEMO_MUTIL_METHOD subscriber:[DemoService class] action:@selector(mutilMethod1)];
[DVEventSubscriber addClasslEvent:kEVENT_SERVICE_DEMO_MUTIL_METHOD subscriber:[DemoService class] action:@selector(mutilMethod2)];
[DVEventSubscriber addClasslEvent:kEVENT_SERVICE_DEMO_MUTIL_METHOD subscriber:[DemoService class] action:@selector(mutilMethod3)];
複製代碼
/*
發送事件能夠同步返回結果, 跟直接調用方法耗時差很少
多參數傳入, 結尾必須加 nil
*/
NSNumber *count = [DVEventPublisher publishClassEvent:kEVENT_SERVICE_DEMO_ADD params:@(1), @(2), nil];
NSString *string = [DVEventPublisher publishClassEvent:kEVENT_SERVICE_DEMO_GET_STRING];
UserModel *user = [DVEventPublisher publishClassEvent:kEVENT_SERVICE_DEMO_GET_OBJECT];
// 發送事件異步回調結果
void(^successBlock)(BOOL) = ^(BOOL status) {
// 處理程序
};
[DVEventPublisher publishClassEvent:kEVENT_SERVICE_DEMO_LOGIN params:@"Hello", @"654321", successBlock, nil];
// 發佈一個類事件能夠順序執行多個類方法
[DVEventPublisher publishClassEvent:kEVENT_SERVICE_DEMO_MUTIL_METHOD];
複製代碼
@interface Demo() <DVEventBusDelegate> // 繼承 'DVEventBusDelegate'
@end
@implementation Demo
/**
事件 綁定 對象方法
實現 'DVEventBusDelegate' 的 'event_method_map' 方法
*/
- (NSDictionary<NSString *,NSString *> *)event_method_map {
return @{
kEVENT_DEMO_ADD : _sel(@selector(addWithA:b:)),
};
}
- (NSNumber *)addWithA:(NSNumber *)a b:(NSNumber *)b {
int ret = [a intValue] + [b intValue];
return @(ret);
}
@end
複製代碼
// 用這個方法註冊, 對象必須繼承'DVEventBusDelegate' 和 實現'event_method_map'
[DVEventSubscriber registerEvents:object];
複製代碼
[DVEventSubscriber addEvent:kEVENT_DEMO_ADD subscriber:object action:@selector(addWithA:b:)];
複製代碼
// 同步返回結果, 如有參數, 結尾要nil
NSNumber *count = [DVEventPublisher publishEvent:kEVENT_DEMO_ADD params:@(1), @(2), nil];
複製代碼
項目 Target -> Build Settings -> Linking ->Other Linker Flags 添加參數: -all_load -ObjC github
在PCH文件導入bash
#import <DVEventBusKit/DVEventBusKit.h>
複製代碼
github地址: github.com/shidavid/DV…
謝謝你們觀看,有興趣麻煩點個星星關注下 😁😁😁異步