2018年11月1日
一.工具类私有库,一般都是给大家一起使用的,基本都是底层的,大家都可以依赖它,他不依赖与任何组件。「所以最好先创建基础库,在创建业务库」
业务类私有库,如宣教库 HuHealtheducationKit(A库),培训库HuTrainKit(B库)。
A库里需要B库的页面, A库就需要dependenceB库;B库如何也需要A库的页面,B库就需要dependenceA库的页面; 这样就会出现循环引用无法同时做出A库和B库,于是我们可以引入秘书机制,引入宣教服务库HuHealtheducationCategoryKit(a库),和培训服务库HuTrainCategoryKit(b库)
这样A库如果需要B库的内容,A库依赖服务库b库;B库如果需要A库的功能,B库依赖a库就可以,这样就不会相互引用了。可以正常做库了
1.目前项目依赖的是CTMediator实现 https://github.com/casatwy/CTMediator
如果获取对象无返回值,或者返回是对象类型 真正跳转代码
[target performSelector:action withObject:params];
关键代码如下:
- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget
{
NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];
NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName];
Class targetClass;
NSObject *target = self.cachedTarget[targetClassString];
if (target == nil) {
targetClass = NSClassFromString(targetClassString);
target = [[targetClass alloc] init];
}
SEL action = NSSelectorFromString(actionString);
if (target == nil) {
// 这里是处理无响应请求的地方之一,这个demo做得比较简单,如果没有可以响应的target,就直接return了。实际开发过程中是可以事先给一个固定的target专门用于在这个时候顶上,然后处理这种请求的
return nil;
}
if (shouldCacheTarget) {
self.cachedTarget[targetClassString] = target;
}
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
}
}
#pragma mark - private methods
- (id)safePerformAction:(SEL)action target:(NSObject *)target params:(NSDictionary *)params
{
NSMethodSignature* methodSig = [target methodSignatureForSelector:action];
if(methodSig == nil) {
return nil;
}
const char* retType = [methodSig methodReturnType];
if (strcmp(retType, @encode(void)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
return nil;
}
if (strcmp(retType, @encode(NSInteger)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
NSInteger result = 0;
[invocation getReturnValue:&result];
return @(result);
}
if (strcmp(retType, @encode(BOOL)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
BOOL result = 0;
[invocation getReturnValue:&result];
return @(result);
}
if (strcmp(retType, @encode(CGFloat)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
CGFloat result = 0;
[invocation getReturnValue:&result];
return @(result);
}
if (strcmp(retType, @encode(NSUInteger)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
NSUInteger result = 0;
[invocation getReturnValue:&result];
return @(result);
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
return [target performSelector:action withObject:params];
#pragma clang diagnostic pop
}
#pragma mark - getters and setters
- (NSMutableDictionary *)cachedTarget
{
if (_cachedTarget == nil) {
_cachedTarget = [[NSMutableDictionary alloc] init];
}
return _cachedTarget;
}
二.具体实现创建宣教库A库,宣教服务a库, 培训库B库,培训服务库b库
1.创建HuHealtheducationKit库 参考:组件化-创建工具类私有库
第一步主要是设置podspec同那个文件
Pod::Spec.new do |s|
s.name = 'HuHealtheducationKit'
s.version = '1.0.5'
s.summary = 'A short description of HuHealtheducationKit.'
s.description = <<-DESC
TODO: Add long description of the pod here.
DESC
s.homepage = 'git@gitlab.317hu.com:HuModularizationLibrary/HuHealtheducationKit'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'wangyu204' => 'wangyu@317hu.com' }
s.source = { :git => 'git@gitlab.317hu.com:HuModularizationLibrary/HuHealtheducationKit.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.ios.deployment_target = '8.0'
#1. 文件所在的路径
s.source_files = 'HuHealtheducationKit/Classes/*'
#2. 需要公开出来的头文件,这样使用方就不需要引入多个头文件,直接引入这个头文件了
s.public_header_files = 'HuHealtheducationKit/Classes/*.h'
#3.预加载头文件,类似于主工程的pch文件,库里面代码就不需要在引入一般如下头文件,可能有先后顺序,一般把基础库写在最前面。
s.prefix_header_contents = '#import <HuConfigsKit/HuConfigsHeader.h>','#import <MJExtension/MJExtension.h>','#import <HuCommonUIKit/HuCommonUIHeader.h>','#import <HuUtilsKit/HuUtilsHeader.h>','#import <HuCategoryKit/HuCategoryHead.h>','#import <HuMainProjectCategoryKit/CTMediator+HuMainProjectCategory.h>','#import <MJRefresh/MJRefresh.h>','#import <HuNetKit/HuNetHeader.h>','#import <IQKeyboardManager/IQKeyboardManager.h>','#import <SDWebImage/UIImageView+WebCache.h>','#import <Masonry/Masonry.h>'
#4.实现页面分层功能
s.subspec 'HuHealtheducation' do |ss|
#4.0注意没有如下预计,因为HuHealtheducation目录下只有m文件夹,没有代码
#ss.source_files =
ss.subspec 'Models' do |sss|
sss.source_files = 'HuHealtheducationKit/Classes/HuHealtheducation/Models/*'
end
ss.subspec 'Utils' do |sss|
#4.1 需要有依赖 因为Utils文件用到了Models目录下面的类,(注意 Models就不能依赖Utils,不然就循环引用了)
sss.dependency 'HuHealtheducationKit/HuHealtheducation/Models'
#4.1.1填写的是组件名+文件夹名,不是物理目录
sss.source_files = 'HuHealtheducationKit/Classes/HuHealtheducation/Utils/*'
end
ss.subspec 'Views' do |sss|
#4.1
sss.dependency 'HuHealtheducationKit/HuHealtheducation/Models'
sss.dependency 'HuHealtheducationKit/HuHealtheducation/Utils'
sss.source_files = 'HuHealtheducationKit/Classes/HuHealtheducation/Views/*'
end
ss.subspec 'ViewControllers' do |sss|
#4.1
sss.dependency 'HuHealtheducationKit/HuHealtheducation/Utils'
sss.dependency 'HuHealtheducationKit/HuHealtheducation/Views'
sss.dependency 'HuHealtheducationKit/HuHealtheducation/WBView'
sss.source_files = 'HuHealtheducationKit/Classes/HuHealtheducation/ViewControllers/*'
end
ss.subspec 'WBView' do |sss|
sss.source_files = 'HuHealtheducationKit/Classes/HuHealtheducation/WBView/*'
end
end
#5.资源文件放xib文件 和图片文件
s.resource_bundles = {
'HuHealtheducationKit' => ['HuHealtheducationKit/Assets/*']
}
#6.依赖库 第3点可能会用到的头文件都需要直接或间接引入该库
s.dependency 'HuMainProjectCategoryKit'
s.dependency 'HuUtilsKit'
s.dependency 'HuCommonUIKit'
s.dependency 'MJExtension', '~> 3.0.13'
s.dependency 'HuNetKit'
s.dependency 'IQKeyboardManager', '~> 5.0.3'
s.dependency 'Masonry'
s.dependency 'SDWebImage', '~> 3.8.0'
s.dependency 'HuSocketKit'
s.dependency 'HuCWStarRateViewKit'
end
对应目录结构如下显示:
1.1几点补充
a.第3点设置的预加载头文件 pod install后就会在如下目录创建pch文件
b.资源文件放在如下右边目录,pod install后 就会在左边出现(配置文件第5点设置的)
2.第二步,创建 Target_HuHealtheducationKit类将需要公共出去的类或对象在个类里实现(因为需要依赖ViewControllers,我们就放在ViewControllers目录里了)【这个类时真正实现提供者】
2.1命名规则参照CTMediator的关键代码 「注意最好按如下约定填写,不然很容易找不到该类,或该方法」
类名:Target_库名。
方法名:Action_类名
// Target_HuHealtheducationKit.h
#import <Foundation/Foundation.h>
@interface Target_HuHealtheducationKit : NSObject
//获取宣教主页
- (id)Action_getHealtheducationController:(NSDictionary *)params;
@end
// Target_HuHealtheducationKit.m
#import "Target_HuHealtheducationKit.h"
#import "MainViewController.h"
@implementation Target_HuHealtheducationKit
//获取宣教主页
- (id)Action_getHealtheducationController:(NSDictionary *)params{
return [[MainViewController alloc] init];
}
@end
2.2补充 如果是简单的获取viewController 我们也可以用如下方法回去 用运行时命令实现不引入头文件
使用:
UIViewController *vc = [[HuControllerId HuControllerShare] getViewControllerWithConName:@“HuWorkerSatisfactionViewController" paramType:HuPushNoParam param:nil];
[nav pushViewController:vc animated:YES];
所以,如果是获取view之类的推荐 用添加一个Action_方法
3.第三步创建宣教服务库HuHealtheducationCategoryKit(a库) 「其实是CTMediator的扩展方法」
3.1同样最主要的也是podspec文件 (该库只有两个文件,只是提供一个秘书中转服务,所以不需要分层这种)
Pod::Spec.new do |s|
s.name = 'HuHealtheducationCategoryKit'
s.version = '1.0.1'
s.summary = 'A short description of HuHealtheducationCategoryKit.'
s.description = <<-DESC
TODO: Add long description of the pod here.
DESC
s.homepage = 'git@gitlab.317hu.com:HuModularizationLibrary/HuHealtheducationCategoryKit'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'wangyu204' => 'wangyu@317hu.com' }
s.source = { :git => 'git@gitlab.317hu.com:HuModularizationLibrary/HuHealtheducationCategoryKit.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.source_files = 'HuHealtheducationCategoryKit/Classes/**/*'
s.prefix_header_contents = '#import <HuConfigsKit/HuConfigsHeader.h>'
s.dependency 'CTMediator'
s.dependency 'HuConfigsKit'
end
3.2命名规范
推荐 CTMediator+库名
eg: CTMediator+HuHealtheducationCategoryKit
// CTMediator+HuHealtheducationCategoryKit.h
#import <Foundation/Foundation.h>
#import <CTMediator/CTMediator.h>
@interface CTMediator(HuHealtheducationCategoryKit)
//获取宣教主页
- (id)getHealtheducationController;
@end
// CTMediator+HuHealtheducationCategoryKit.m
#import "CTMediator+HuHealtheducationCategoryKit.h"
@implementation CTMediator (HuHealtheducationCategoryKit)
//获取宣教
- (id)getHealtheducationController{
return [self performTarget:HuHealtheducationKit action:@"getHealtheducationController" params:nil shouldCacheTarget:NO];
}
@end
4.具体使用
需要用到A库的MainViewController (主干或其他库)引入对应的秘书服务库即可
#import <HuHealtheducationCategoryKit/CTMediator+HuHealtheducationCategoryKit.h>
UIViewController *MPVc= [[CTMediator sharedInstance] getHealtheducationController];
4.1补充 如果抽离较慢我们可以 主干代码当成一个大的业务库C, 在主干里面创建一个 Target_HuMainProjectKit类
在创建一个主干的秘书服务库 CTMediator+HuMainProjectCategoryKit
这样需要抽离的库先放主干,等主干抽离好了,在把对应的服务方法放到对应的库哪里即可
eg:先放在主干里面
#import "CTMediator+HuMainProjectCategoryKit.h"
//隐藏或者显示tabbar
- (void)isHidenTabBar:(BOOL)isHiden vc:(UIViewController *)vc{
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setObject:@(isHiden) forKey:@"isHiden"];
[dic setObject:vc forKey:@"vc"];
[self performTarget: HuMainProjectKit action:@"isHidenTabBar" params:dic shouldCacheTarget:NO];
}
等抽离好了
- (void)isHidenTabBar:(BOOL)isHiden vc:(UIViewController *)vc{
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setObject:@(isHiden) forKey:@"isHiden"];
[dic setObject:vc forKey:@"vc"];
[self performTarget:HuLoginAndRegisterKit action:@"isHidenTabBar" params:dic shouldCacheTarget:NO];
}
5.用同样的方法就可以抽离培训库 HuTrainKit(B库)和培训服务库 HuTrainCategoryKit(b库),就可以上传做库了。做好后,就主干集成这些库,删除报错的重复文件即可。
如果您发现本文对你有所帮助,如果您认为其他人也可能受益,请把它分享出去。