iOS插件开发思想

随着公司业务的发展,公司的播放器功能也越来越复杂,另外播放器作为通用功能,还需要支持不同业务线的播放器的定制,因此想着我们是不是可以借鉴前端开发一些插件化思想,把我们播放器的每个功能都当做一个插件,各个业务根据自己的喜好去定制不同的插件:

  • 下载
  • 分享
  • 字幕
  • 弹幕
  • 清晰度
  • 速率
  • ……

对于播放器来说只需要维护通用的播放器的一些状态,比如播放的开始播放,暂停,结束,缓存进度,播放进度等。
因此希望通过下面这个Demo,模拟器了一下如何使用原生的方式模拟一下插件的开发思想。

一.整个代码的结构如下

image.png

主要包含CCPlayer, CCPlayerBuilder,CCPlayerPlugin, CCPlayerConfig 这四个主要文件,接下来我们一个个介绍,这几个类分别做了哪些事情,提供了哪些方法?

二. 接下来我们详细介绍一下每个类扮演什么角色

1. CCPlayer

这个是一个通用的管理配置和插件的地方

@class CCPlayerBuilder;
@interface CCPlayer : NSObject

/** 单例 */
+ (id)sharedInstance;

/** 添加构造器 */
- (void)addPlayerBuilder:(CCPlayerBuilder *)builder;

/** 开启插件 */
- (void)startPlugins;

/** 停止插件 */
- (void)stopPlugins;

/** 获取所有插件 */
- (NSMutableSet *)getPlugins;

/** 移除所有插件 */
- (void)removeAllPlugin;

@end

复制代码
2. CCPlayerBuilder

这个一个专门管理插件的地方,同时承接插件的代理回调

@interface CCPlayerBuilder : NSObject

@property (nonatomic, weak) id<CCPlayerPluginListenerDelegate> pluginListener;

/** 获取所有插件 */
- (NSMutableSet *)getPlugins;

/** 移除所有插件 */
- (void)removeAllPlugin;

/** 根据tag获取插件 */
- (CCPlayerPlugin *)getPluginWithTag:(NSString *)tag;

/** 添加插件 */
- (void)addPlugin:(CCPlayerPlugin *)plugin;

/// 移除插件
/// @param tag 插件名称
- (void)removePluginWithTag:(NSString *)tag;

/** 移除插件 */
- (void)removePlugin:(CCPlayerPlugin *)plugin;

/** 是否包含某个插件 */
- (BOOL)isContainPlugin:(CCPlayerPlugin *)plugin;

@end

复制代码
3. CCPlayerPlugin
  • 定义插件的生命周期
  • 插件的优先级
  • 插件的配置
#import <Foundation/Foundation.h>
#import "CCPlayerPluginConfig.h"

NS_ASSUME_NONNULL_BEGIN

/** 设置优先级 */
typedef NS_OPTIONS(NSUInteger, CCPlayerPluginPriority) {
    CCPlayerPluginPriorityHigh,
    CCPlayerPluginPriorityMiddle,
    CCPlayerPluginPriorityLow
};

#pragma mark - CCPlayerPluginListenerDelegate
@protocol CCPlayerPluginProtocol;

// 添加时间监听代理
@protocol CCPlayerPluginListenerDelegate <NSObject>

@optional

- (void)onInit:(id<CCPlayerPluginProtocol>)plugin;
- (void)onStart:(id<CCPlayerPluginProtocol>)plugin;
- (void)onStop:(id<CCPlayerPluginProtocol>)plugin;
- (void)onDestroy:(id<CCPlayerPluginProtocol>)plugin;

/** 插件的优先级 */
- (void)onPriority:(id<CCPlayerPluginProtocol>)plugin;

@end


#pragma mark - CCPlayerPluginProtocol

@protocol CCPlayerPluginProtocol <NSObject>

@required

/** 开始 */
- (void)start;

/** 结束 */
- (void)stop;

/** 销毁 */
- (void)destroy;

/** 添加监听 */
- (void)setupPluginListener:(id<CCPlayerPluginListenerDelegate>)pluginListener;

/** 获取插件tag */
- (NSString *)getTag;

/** 插件的优先级 */
- (CCPlayerPluginPriority)pluginPriority;

@end


#pragma mark - CCPlayerPlugin

@interface CCPlayerPlugin : NSObject <CCPlayerPluginProtocol>

/** 插件配置类 */
@property (nonatomic, strong) CCPlayerPluginConfig *pluginConfig;

@end

复制代码
4. CCPlayerConfig

这个类做一些通用的配置

三、如何写插件?

为了能够让大家更好的理解这几个类是怎么联系的,写了两个简单的插件,下载插件和分享插件

1. 分享插件

  • 分享的配置
@interface CCPlayerShareConfig : NSObject

+ (CCPlayerShareConfig *)defaultConfig;

/** 应用id */
@property (nonatomic, copy) NSString *appId;
/** 引用密码 */
@property (nonatomic, copy) NSString *appSecret;

@end

复制代码
  • 分享插件

具体的插件的实现,可以下载代码,看细节

@protocol CCPlayerSharePluginDelegate <NSObject>

/** 分享平台 */
- (void)sharePlatform:(NSString *)platform;

- (void)shareError:(NSString *)error;

@end

@interface CCPlayerSharePlugin : CCPlayerPlugin

/** 添加分享平台 */
- (void)addPlatform:(NSArray *)platforms;

@property (nonatomic, assign) id<CCPlayerSharePluginDelegate> delegate;

@property (nonatomic, strong) CCPlayerShareConfig *config;

@end

复制代码

2. 下载插件

  • 下载配置
@interface CCPlayerDownloadConfig : CCPlayerPluginConfig

+ (CCPlayerDownloadConfig *)defaultConfig;

/** 下载URL */
@property (nonatomic, copy) NSString *videoUrl;

/** 保存地址 */
@property (nonatomic, copy) NSString *saveFilePath;

@end

复制代码
  • 下载插件
@protocol CCPlayerDownloadPluginDelegate<NSObject>

/** 开始下载 */
- (void)startDownLoadWithUrl:(NSString *)url;
/** 下载中 */
- (void)downloadWithProgress:(float)process;
/** 开始完成 */
- (void)finishDownloadLoadWithUrl:(NSString *)url;

@end

@interface CCPlayerDownloadPlugin : CCPlayerPlugin

@property (nonatomic, strong) CCPlayerDownloadConfig *config;

@property (nonatomic, weak) id<CCPlayerDownloadPluginDelegate> delegate;

@end

复制代码

四、如何使用?

#import "ViewController.h"
#import "CCPlayer.h"
#import "CCPlayerBuilder.h"
#import "CCPlayerSharePlugin.h"
#import "CCPlayerDownloadPlugin.h"

@interface ViewController ()<CCPlayerPluginListenerDelegate, CCPlayerSharePluginDelegate, CCPlayerDownloadPluginDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];

    // 测试插件
    CCPlayer *player = [CCPlayer sharedInstance];
    CCPlayerBuilder *playerBuilder = [[CCPlayerBuilder alloc] init];
    playerBuilder.pluginListener = self; // pluginListener 回调 plugin 的相关事件
        
    CCPlayerSharePlugin *sharePlugin = [[CCPlayerSharePlugin alloc] init];
    sharePlugin.delegate = self;
    [playerBuilder addPlugin:sharePlugin];
    
    // 配置下载插件
    CCPlayerDownloadPlugin *downloadPlugin = [[CCPlayerDownloadPlugin alloc] init];
    
    CCPlayerDownloadConfig *config = [[CCPlayerDownloadConfig alloc] init];
    config.videoUrl = @"http://www.baidu.com";
    config.saveFilePath = @"/usr/download/video";
    downloadPlugin.config = config;
    
    downloadPlugin.delegate = self;
    [playerBuilder addPlugin:downloadPlugin];

    [player addPlayerBuilder:playerBuilder];
    [sharePlugin start];
    [downloadPlugin start];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(100 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // 移除插件
        [playerBuilder removePlugin:downloadPlugin];
        NSLog(@"插件%@", [player getPlugins]);
    });

    NSLog(@"插件个数%@", [player getPlugins]);
    NSLog(@"tag获取的插件是%@", [playerBuilder getPluginWithTag:@"downloadPlugin"]);
    NSLog(@"是否包含分享插件----%@", @([playerBuilder isContainPlugin:sharePlugin]));
}

#pragma mark - CCPlayerPluginListenerDelegate
- (void)onInit:(id<CCPlayerPluginProtocol>)plugin {
    
}

- (void)onStart:(id<CCPlayerPluginProtocol>)plugin {
    NSLog(@"插件是啥%@", plugin);
}

- (void)onStop:(id<CCPlayerPluginProtocol>)plugin {
    
}

- (void)onDestroy:(id<CCPlayerPluginProtocol>)plugin {
    
}

- (void)onPriority:(id<CCPlayerPluginProtocol>)plugin {
    
}

#pragma mark - CCPlayerSharePluginDelegate
- (void)sharePlatform:(NSString *)platform {
    NSLog(@"分享平台---%@", platform);
}

- (void)shareError:(NSString *)error {
    NSLog(@"错误信息是---%@", error);
}

#pragma mark - CCPlayerDownloadPluginDelegate

- (void)startDownLoadWithUrl:(NSString *)url {
    NSLog(@"开始下载--%@", url);
}

- (void)downloadWithProgress:(float)process {
    NSLog(@"下载进度--%@", @(process));
}

- (void)finishDownloadLoadWithUrl:(NSString *)url {
    NSLog(@"下载完成--%@", url);
}

@end

复制代码

五、由于代码比较简单,具体实现细节可查看

传送门

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享