讲解通过协议实现组件化解耦

栏目: IOS · 发布时间: 5年前

内容简介:GitHub地址:讲解通过协议实现组件化解耦的直播demo。 现在是将各个组件代码和主工程放到了一个Git工程里,当然实际应该是放到不同Git工程的。

GitHub地址:

https://github.com/mlcldh/LCLive

讲解通过协议实现组件化解耦的直播demo。 现在是将各个组件代码和主工程放到了一个Git工程里,当然实际应该是放到不同Git工程的。

主工程依赖这些组件。LCLive是主工程。 LCMediator是调度层中间件。 LCBase是基础模块,封装公共类和方法。 LCWeb是h5、weex模块。 LCChat是私信模块。 LCMomment是朋友圈模块。

Podfile如下:

platform :ios, '8.0'
use_frameworks!

source ' 

target 'LCLive' do

pod 'LCMediator', :path => '../LCMediator'
pod 'LCBase', :path => '../LCBase'
pod 'LCUser', :path => '../LCUser'
pod 'LCShare', :path => '../LCShare'
pod 'LCMe', :path => '../LCMe'
pod 'LCChat', :path => '../LCChat'
pod 'LCWeb', :path => '../LCWeb'
pod 'LCMoment', :path => '../LCMoment'
pod 'LCLaunch', :path => '../LCLaunch'

end

中间件是LCMediator,它里面定义了User、私信、Web、Moment等协议,供相应组件实现了和供其他组件调用。

讲解通过协议实现组件化解耦

通过NSClassFromString方法获取到类后,写代码让该类执行类方法时,Xcode不会给提示,毕竟Xcode无法只提供Class这一个类型就判断出具体是那种类。既然不给提示,就要自己将代码复制过去,然后编译也没问题。但如果复制成了其他类方法,只要这个类方法能够引用到,编译就不会报错,这样就会出问题了。这样因为Xcode对类方法编译不够友好,将所有组件协议方法都写成实例方法。

LCMediator的LCMediatorHeader里通过传入的组件协议返回实现该协议的类的实例。 方法LCModuleInstanceFromProtocol获取到的也就只是实例对象。调用组件协议实例时,不需要提前注册,LCModuleInstanceFromProtocol内部做了懒加载处理。

/**根据传入的组件协议返回实现该协议的类的对象*/
NS_INLINE id LCModuleInstanceFromProtocol(Protocol *protocol) {
    NSString *className = NSStringFromProtocol(protocol);
    Class aClass = NSClassFromString(className);
//    NSLog(@"class %@,%@",className,aClass);
    static NSMutableDictionary *modulesDictionary = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        modulesDictionary = [NSMutableDictionary dictionary];
    });
    id module = modulesDictionary[className];
    if (!module) {
        module = [[aClass alloc]init];
        modulesDictionary[className] = module;
    }
    if ([module conformsToProtocol:protocol]){
        return module;
    }
    return nil;
}

#define LCModuleInstance(module,LCModuleProtocol) id module = LCModuleInstanceFromProtocol(@protocol(LCModuleProtocol));
#define LCGetModuleInstance(LCModuleProtocol) ((id)(LCModuleInstanceFromProtocol(@protocol(LCModuleProtocol))))
/**用户信息模块*/
@protocol LCUserModule /**用户id*/
- (NSString *)userId;
/**token*/
- (NSString *)token;
/**用户昵称*/
- (NSString *)nickname;
/**用户头像url地址*/
- (NSString *)avatarUrlString;

@end
@interface LCUserModule : NSObject@end
@implementation LCUserModule

- (NSString *)userId {
    return @"abc123100";
}
- (NSString *)token {
    return @"qwe007what";
}
- (NSString *)nickname {
    return @"李明";
}
- (NSString *)avatarUrlString {
    return @"https://ss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=3843887011,4044287239&fm=173&app=25&f=JPEG?w=218&h=146&s=F81821D40331ABCC106BAA8003008088";
//    return @"https://avatar.csdn.net/7/5/6/1_mlcldh.jpg?1532075030";
}

@end
_nicknameLabel.text = [LCGetModuleInstance(LCUserModule) nickname];

LCWeb是h5、weex模块。 LCWebModule里面实现协议提供跳转到H5的方法。

@implementation LCWebModule

- (void)pushWebViewControllerWithUrlString:(NSString *)urlString fromViewController:(UIViewController *)viewController {
    LCWebViewController *webVC = [[LCWebViewController alloc]init];
    webVC.urlString = urlString;
    [viewController.navigationController pushViewController:webVC animated:YES];
}

@end

LCChat是私信模块。LCChatModule提供读取消息未读数和跳转到单例详情的方法。

@implementation LCChatModule

- (UIViewController *)sessionListViewController {
    LCSessionListViewController *vc = [[LCSessionListViewController alloc]init];
    return vc;
}
- (NSUInteger)ureandCount {
    return 3;
}
- (void)pushUserChatViewControllerWithUserId:(NSString *)userId fromViewController:(UIViewController *)viewController {
    LCUserChatViewController *userChatVC = [[LCUserChatViewController alloc]init];
    [viewController.navigationController pushViewController:userChatVC animated:YES];
}

@end

LCWeb是h5、weex模块。 LCWebModule里面实现协议提供跳转到H5的方法。

@implementation LCWebModule

- (void)pushWebViewControllerWithUrlString:(NSString *)urlString fromViewController:(UIViewController *)viewController {
    LCWebViewController *webVC = [[LCWebViewController alloc]init];
    webVC.urlString = urlString;
    [viewController.navigationController pushViewController:webVC animated:YES];
}

@end

LCChat是私信模块。LCChatModule提供读取消息未读数和跳转到单例详情的方法。

@implementation LCChatModule

- (UIViewController *)sessionListViewController {
    LCSessionListViewController *vc = [[LCSessionListViewController alloc]init];
    return vc;
}
- (NSUInteger)ureandCount {
    return 3;
}
- (void)pushUserChatViewControllerWithUserId:(NSString *)userId fromViewController:(UIViewController *)viewController {
    LCUserChatViewController *userChatVC = [[LCUserChatViewController alloc]init];
    [viewController.navigationController pushViewController:userChatVC animated:YES];
}

@end

优点:

  1. 组件间的调用更为方便。

  2. 解耦代码量少,实现方便,以后维护也方便。

  3. 协议方法改变后,编译就会报错,避免代码修改遗漏。

  4. 协议方法未实现的话,会报编译警告。

  5. 方法查找容易,调用高效。

  6. 不需要注册即可调用。

缺点:

  1. 组件的方法调用分散。

  2. 内存中维护映射表。

  3. 协议方法有可能未实现,调用会导致崩溃。

使用注意事项:

  1. 组件协议的方法都要写成实例方法,不要写成类方法。

  2. 组件协议的方法都要实现,因为调用时不会去判断方法有没有实现。

  3. 获取组件协议实现的实例对象,只能使用LCModuleInstance(module,LCModuleProtocol) 或LCGetModuleInstance(LCModuleProtocol)这两个个宏,从而避免直接使用LCModuleInstanceFromProtocol获取到实现类,让实现类执行了其并不遵守的协议方法。

  4. 组件协议实现的实例对象只是用来负责组件通信的,不要用它们来存储其他东西,因为这些事例对象一直不会去释放,存储太多东西,容易出现内存占用过多的问题。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大型网站技术架构

大型网站技术架构

李智慧 / 电子工业出版社 / 2013-9-1 / 59.00元

《大型网站技术架构:核心原理与案例分析》通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计案例,为读者呈现一幅包括技术选型、架构设计、性能优化、Web 安全、系统发布、运维监控等在内的大型网站开发全景视图。 《大型网站技术架构:核心原理与案例分析》不仅适用于指导网站工程师、架构师进行网站技术架构设计,也可用于指导产品经......一起来看看 《大型网站技术架构》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具