Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
chaidongpeng committed Jul 10, 2021
0 parents commit 9b3ee8e
Show file tree
Hide file tree
Showing 33 changed files with 2,043 additions and 0 deletions.
98 changes: 98 additions & 0 deletions CDPStateManager/CDPStateManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// CDPStateManager.h
// stateManager
//
// Created by CDP on 2021/7/10.
// 状态管理类

#import <Foundation/Foundation.h>

#import "CDPStateManagerProtocol.h"

/// action回调block
typedef NSDictionary *_Nullable(^CDPHandleActionBlock)(NSDictionary * _Nullable parameters);
/// 同步notification状态回调block
typedef NSDictionary *_Nullable(^CDPHandleNotificationBlock)(NSNotification * _Nonnull notification);


@interface CDPStateManager : NSObject
/// 使用方法
/// 1. 用 registerAction 方法注册 改变状态 处理回调 (只用注册一次即可,可在 AppDelegate 初始化时就把各状态注册好)
/// 2. import "CDPStateManager.h",将需要管理的 object 遵守 CDPStateManagerProtocol 协议,并添加进 对应状态 的管理池
/// 3. 实现 CDPStateManagerProtocol 所需协议方法,接收 状态同步
///
/// 其他:
/// 1. 如果某控件需要 主动去改变 某已管理状态,则调用该状态对应 已注册action 即可,即调用 actionWithParameters: stateIdentifier: 方法
/// 2. 如果需要将 已管理状态 与 已有notification通知 同步,则用 syncNotificationName 方法进行绑定

/// 单例对象
+ (instancetype _Nonnull )defaultManager;

#pragma mark - 管理控件

/// 获取 identifier 对应状态的 object 管理池
/// @param identifier 对应 状态 唯一标识
- (NSHashTable *_Nonnull)getHashTableWithIdentifier:(nonnull NSString *)identifier;

/// 将 相关控件 添加进 identifier 对应 状态管理池 中 (控件释放后 内部会自动对其 移除, 不需要 主动移除)
/// @param object 相关控件
/// @param identifier 对应 状态 唯一标识
- (void)addObject:(nonnull id <CDPStateManagerProtocol>)object stateIdentifier:(nonnull NSString *)identifier;

/// 主动将 相关控件 从 identifier 对应 状态管理池 中移除
/// @param object 相关控件
/// @param identifier 对应 状态 唯一标识
- (void)removeObject:(nonnull id <CDPStateManagerProtocol>)object stateIdentifier:(nonnull NSString *)identifier;

/// 清空 identifier 对应 状态管理池 (慎用!!!)
/// @param identifier 对应 状态 唯一标识
- (void)removeAllObjectsWithStateIdentifier:(nonnull NSString *)identifier;

#pragma mark - action

/// 注册 identifier 对应状态 相关 action,如果该状态已注册 action,则自动替换 (状态 与 action 一一对应)
/// @param identifier 对应 状态 唯一标识
/// @param block 进行action回调,进行切换状态等相关逻辑处理
///
/// 通过action改变状态时,会将 parameters 通过 block 回调,可以在 block 里根据 传参 进行相关逻辑处理,然后将结果数据通过 字典 封装返回,内部会将该 字典 通过 CDPStateManagerProtocol 协议方法进行全站同步管理
///
/// 注:回调 字典 里如果有 @"stateManagerNotSync" : @"1" ,则此次结果 字典 不会进行全站同步
- (void)registerActionWithStateIdentifier:(nonnull NSString *)identifier
completion:(nonnull CDPHandleActionBlock)block;

/// 移除 identifier 对应状态 相关 action
/// @param identifier 对应 状态 唯一标识
- (void)removeActionWithStateIdentifier:(nonnull NSString *)identifier;

/// 执行 identifier 对应状态 相关 action,以改变状态 (必须先用 registerAction 添加再使用)
/// @param parameters action 改变状态要用到的传参
/// @param identifier 对应 状态 唯一标识
- (void)actionWithParameters:(nullable NSDictionary *)parameters
stateIdentifier:(nonnull NSString *)identifier;

#pragma mark - 同步通知
/// 如果有状态存在 不通过 CDPStateManager 管理,而是用 notification 通知 管理的情况,可以用以下方法将已管理的 状态 与该通知绑定同步

/// 将 notificationName 对应的通知 与 identifier 对应状态 进行同步绑定,使该 状态 可以被 notification 进行状态同步
/// 状态 与 通知 绑定关系为 多对多,及 一种状态可绑定多个通知 ,一个通知也可同步多个状态
/// @param notificationName 要同步的广播通知名称
/// @param identifier 被同步的 对应 状态 唯一标识
/// @param block 收到 notification 进行的 block 同步回调,进行相关逻辑处理
///
/// 当收到 notification 时,会将其通过 block 回调,可以在 block 里根据 收到的 notification 进行相关逻辑处理转换,然后将结果数据通过 字典 封装返回,内部会将该 字典 通过 CDPStateManagerProtocol 协议方法进行全站同步管理
///
/// 注:回调 字典 里如果有 @"stateManagerNotSync" : @"1" ,则此次结果 字典 不会进行全站同步
- (void)syncNotificationName:(nonnull NSNotificationName)notificationName
toStateIdentifier:(nonnull NSString *)identifier
handle:(nonnull CDPHandleNotificationBlock)block;

/// 将 identifier 对应状态 与 notificationName 对应的通知 解除状态同步
/// @param notificationName 要同步的广播通知名称
/// @param identifier 被同步的 对应 状态 唯一标识
- (void)unsyncNotificationName:(nonnull NSNotificationName)notificationName
toStateIdentifier:(nonnull NSString *)identifier;


@end


235 changes: 235 additions & 0 deletions CDPStateManager/CDPStateManager.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
//
// CDPStateManager.m
// stateManager
//
// Created by CDP on 2021/7/10.
//

#import "CDPStateManager.h"

#import "CDPStateManagerObjectPool.h"
#import "CDPStateManagerActionPool.h"
#import "CDPStateManagerNotificationPool.h"

#define CDPStateNotificationKeyPrefix @"CDPStateNotification_"

@interface CDPStateManager ()

@property (nonatomic, strong) CDPStateManagerObjectPool *objectPool; //object储存池

@property (nonatomic, strong) CDPStateManagerActionPool *actionPool; //action储存池

@property (nonatomic, strong) CDPStateManagerNotificationPool *notificationPool; //notification相关储存池

@end

@implementation CDPStateManager

+ (instancetype)defaultManager {
static CDPStateManager *manager;
static dispatch_once_t once;
dispatch_once(&once, ^{
manager = [[CDPStateManager alloc] init];
});
return manager;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - 管理控件
//获取 identifier 对应状态的 object 管理池
- (NSHashTable *_Nonnull)getHashTableWithIdentifier:(nonnull NSString *)identifier {
return [self.objectPool getHashTableWithIdentifier:identifier];
}
//将 相关控件 添加进 identifier 对应 状态管理池 中 (控件释放后 内部会自动对其 移除, 不需要 主动移除)
- (void)addObject:(id<CDPStateManagerProtocol>)object stateIdentifier:(NSString *)identifier {
if ([object conformsToProtocol:@protocol(CDPStateManagerProtocol)]) {
[self.objectPool addObject:object stateIdentifier:identifier];
}
}
//主动将 相关控件 从 identifier 对应 状态管理池 中移除
- (void)removeObject:(id<CDPStateManagerProtocol>)object stateIdentifier:(NSString *)identifier {
if ([object conformsToProtocol:@protocol(CDPStateManagerProtocol)]) {
[self.objectPool removeObject:object stateIdentifier:identifier];
}
}
//清空 identifier 对应 状态管理池 (慎用!!!)
- (void)removeAllObjectsWithStateIdentifier:(NSString *)identifier {
[self.objectPool removeAllObjectsWithStateIdentifier:identifier];
}

#pragma mark - action

//注册 identifier 对应状态 相关 action,如果该状态已注册 action,则自动替换 (状态 与 action 一一对应)
- (void)registerActionWithStateIdentifier:(NSString *)identifier completion:(CDPHandleActionBlock)block {
if ([identifier isKindOfClass:[NSString class]] &&
identifier.length > 0 &&
block) {
NSDictionary *blockDic = @{@"block": [block copy]};
[self.actionPool saveActionConfigDic:blockDic identifier:identifier];
}
}
//移除 identifier 对应状态 相关 action
- (void)removeActionWithStateIdentifier:(nonnull NSString *)identifier {
[self.actionPool removeActionWithStateIdentifier:identifier];
}
//执行 identifier 对应状态 相关 action,以改变状态 (必须先用 registerAction 添加再使用)
- (void)actionWithParameters:(nullable NSDictionary *)parameters stateIdentifier:(nonnull NSString *)identifier {
if ([identifier isKindOfClass:[NSString class]] && identifier.length > 0) {
//获取actionBlock
NSDictionary *blockDic = [self.actionPool getActionConfigDicWithIdentifier:identifier];

if (blockDic.allKeys.count == 0) {
return;
}
CDPHandleActionBlock block = [blockDic objectForKey:@"block"];

//获取action处理后的数据
NSDictionary *completionDic = nil;
if (block) {
completionDic = block(parameters);
}
if ([completionDic isKindOfClass:[NSDictionary class]]) {
NSString *notSync = [completionDic objectForKey:@"stateManagerNotSync"];
if ([notSync isKindOfClass:[NSString class]] && [notSync isEqualToString:@"1"]) {
//不进行同步回调
return;
}
}
//对该状态关联的管理控件发送回调
[self actionStateChangedWithDic:completionDic parameters:parameters identifier:identifier];
}
}
//发送action回调
- (void)actionStateChangedWithDic:(NSDictionary *)dic parameters:(NSDictionary *)parameters identifier:(NSString *)identifier {
if ([identifier isKindOfClass:[NSString class]] && identifier.length > 0) {
//获取对应状态的 控件管理池容器
NSHashTable *hashTable = [self.objectPool getHashTableWithIdentifier:identifier];

for (id object in hashTable) {
//判断CDPStateManagerProtocol协议
if ([object conformsToProtocol:@protocol(CDPStateManagerProtocol)] &&
[object respondsToSelector:@selector(receiveStateActionWithDic:parameters:stateIdentifier:)]) {
[object receiveStateActionWithDic:dic parameters:parameters stateIdentifier:identifier];
}
}
}
}

#pragma mark - 同步通知

//将 notificationName 对应的通知 与 identifier 对应状态 进行同步绑定,使该 状态 可以被 notification 进行状态同步
- (void)syncNotificationName:(nonnull NSNotificationName)notificationName
toStateIdentifier:(nonnull NSString *)identifier
handle:(nonnull CDPHandleNotificationBlock)block {
if ([identifier isKindOfClass:[NSString class]] &&
identifier.length > 0 &&
[notificationName isKindOfClass:[NSString class]] &&
notificationName.length > 0 &&
block) {
//监听该通知
if (![self.notificationPool.listenNotificationArr containsObject:notificationName]) {
[self.notificationPool.listenNotificationArr addObject:notificationName];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:notificationName object:nil];
}
//将状态与通知绑定
[self.notificationPool addSyncStateIdentifier:identifier forNotificationName:notificationName];
//保存对应的block回调
NSDictionary *blockDic = @{@"block": [block copy]};
NSString *actionKey = [self getNotificationActionKeyWithStateIdentifier:identifier notificationName:notificationName];
[self.actionPool saveActionConfigDic:blockDic identifier:actionKey];
}
}
//将 identifier 对应状态 与 notificationName 对应的通知 解除状态同步
- (void)unsyncNotificationName:(nonnull NSNotificationName)notificationName toStateIdentifier:(nonnull NSString *)identifier {
if ([identifier isKindOfClass:[NSString class]] &&
identifier.length > 0 &&
[notificationName isKindOfClass:[NSString class]] &&
notificationName.length > 0) {
//解除绑定
[self.notificationPool removeSyncStateIdentifier:identifier forNotificationName:notificationName];
//移除对应block回调
NSString *actionKey = [self getNotificationActionKeyWithStateIdentifier:identifier notificationName:notificationName];
[self.actionPool removeActionWithStateIdentifier:actionKey];

//检查是否可移除监听通知
if ([self.notificationPool getAllStateIdentifierWithNotificationName:notificationName].count == 0 &&
[self.notificationPool.listenNotificationArr containsObject:notificationName]) {

[self.notificationPool.listenNotificationArr removeObject:notificationName];
[[NSNotificationCenter defaultCenter] removeObserver:self name:notificationName object:nil];
}
}
}
//收到通知进行处理并回调
- (void)receiveNotification:(NSNotification *)notification {
if (notification &&
[notification.name isKindOfClass:[NSString class]] &&
notification.name.length > 0) {
//获取所有绑定的自定义状态
NSArray *stateArr = [self.notificationPool getAllStateIdentifierWithNotificationName:notification.name];
for (NSString *identifier in stateArr) {
//获取对应block
NSString *actionKey = [self getNotificationActionKeyWithStateIdentifier:identifier notificationName:notification.name];
NSDictionary *blockDic = [self.actionPool getActionConfigDicWithIdentifier:actionKey];
if (blockDic.allKeys.count == 0) {
continue;
}
CDPHandleNotificationBlock block = [blockDic objectForKey:@"block"];
//获取action处理后的数据
NSDictionary *completionDic = nil;
if (block) {
completionDic = block(notification);
}
if ([completionDic isKindOfClass:[NSDictionary class]]) {
NSString *notSync = [completionDic objectForKey:@"stateManagerNotSync"];
if ([notSync isKindOfClass:[NSString class]] && [notSync isEqualToString:@"1"]) {
//不进行同步回调
return;
}
}
//对该自定义状态所管理控件发送同步回调
[self syncNotificationWithDic:completionDic notification:notification identifier:identifier];
}
}
}
//发送notification通知同步回调
- (void)syncNotificationWithDic:(NSDictionary *)dic notification:(NSNotification *)notification identifier:(NSString *)identifier {
if ([identifier isKindOfClass:[NSString class]] && identifier.length > 0) {
//获取对应状态的 控件管理池容器
NSHashTable *hashTable = [self.objectPool getHashTableWithIdentifier:identifier];

for (id object in hashTable) {
//判断CDPStateManagerProtocol协议
if ([object conformsToProtocol:@protocol(CDPStateManagerProtocol)] &&
[object respondsToSelector:@selector(receiveStateNotificationSyncWithDic:notification:stateIdentifier:)]) {
[object receiveStateNotificationSyncWithDic:dic notification:notification stateIdentifier:identifier];
}
}
}
}
//获取对应状态处理notification数据的block的key
- (NSString *)getNotificationActionKeyWithStateIdentifier:(nonnull NSString *)identifier notificationName:(nonnull NSNotificationName)notificationName {
return [NSString stringWithFormat:@"%@%@_%@", CDPStateNotificationKeyPrefix, notificationName, identifier];
}
#pragma mark - getter
- (CDPStateManagerObjectPool *)objectPool {
if (_objectPool == nil) {
_objectPool = [CDPStateManagerObjectPool new];
}
return _objectPool;
}
- (CDPStateManagerActionPool *)actionPool {
if (_actionPool == nil) {
_actionPool = [CDPStateManagerActionPool new];
}
return _actionPool;
}
- (CDPStateManagerNotificationPool *)notificationPool {
if (_notificationPool == nil) {
_notificationPool = [CDPStateManagerNotificationPool new];
}
return _notificationPool;
}

@end
28 changes: 28 additions & 0 deletions CDPStateManager/CDPStateManagerProtocol.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// CDPStateManagerProtocol.h
// stateManager
//
// Created by CDP on 2021/7/10.
// 涉及状态管理的 object 需要遵循的协议 ,并通过 CDPStateManager 管理使用

@protocol CDPStateManagerProtocol <NSObject>

@optional

/// 收到 状态改变 回调,可进行改变后的逻辑处理
/// @param dic 执行 action 时通过 block 回调的用来 同步状态数据的 字典
/// @param parameters 执行 action 时的 传参,可与 当前数据进行匹配 是否对应
/// @param identifier 对应 状态 唯一标识
- (void)receiveStateActionWithDic:(NSDictionary *)dic
parameters:(NSDictionary *)parameters
stateIdentifier:(NSString *)identifier;

/// 收到 通知 的同步回调,可进行对应逻辑处理
/// @param dic 对收到的 notification 用 block 回调处理后的 同步数据
/// @param notification 收到的 notification 通知
/// @param identifier 对应 状态 唯一标识
- (void)receiveStateNotificationSyncWithDic:(NSDictionary *)dic
notification:(NSNotification *)notification
stateIdentifier:(NSString *)identifier;

@end
29 changes: 29 additions & 0 deletions CDPStateManager/Pool/CDPStateManagerActionPool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// CDPStateManagerActionPool.h
// stateManager
//
// Created by CDP on 2021/7/10.
// action 储存池

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface CDPStateManagerActionPool : NSObject

/// 保存状态对应action
/// @param configDic 对应action相关设置
/// @param identifier 对应 状态 唯一标识
- (void)saveActionConfigDic:(NSDictionary *)configDic identifier:(NSString *)identifier;

/// 移除 identifier 对应状态 相关 action
/// @param identifier 对应 状态 唯一标识
- (void)removeActionWithStateIdentifier:(NSString *)identifier;

/// 获取状态对应action的相关设置
/// @param identifier 对应 状态 唯一标识
- (NSDictionary *)getActionConfigDicWithIdentifier:(NSString *)identifier;

@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 9b3ee8e

Please sign in to comment.