JLChen
2021-04-30 a5247b61d585627a1a7b1e1f35f34de9f0af9fba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//
//  DHServiceManager.m
//  DHHive
//
//  Created by iblue on 2017/7/12.
//  Copyright © 2017年 jiangbin. All rights reserved.
//
 
#import "DHServiceManager.h"
#import "DHServiceProtocol.h"
#import "DHImplementObject.h"
 
@interface DHServiceManager ()
@property (nonatomic, strong) NSMutableDictionary< NSString*, DHImplementObject*> *dicServiceProtocol;
@property (nonatomic, strong) NSRecursiveLock *lock;
@end
 
@implementation DHServiceManager
 
+ (instancetype)sharedInstance
{
    static id sharedInstance = nil;
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}
 
 
- (void)registerService:(Protocol *)service implClass:(Class)implClass
{
    if (service == nil || implClass == nil) {
        NSLog(@"🐝🐝 DHServiceManager:: service and implClass must not be nil...");
        return;
    }
    
    //CheckService
    if ([self isServiceRegisted:service]) {
        NSLog(@"🐝🐝 DHServiceManager:: %@, service has been registed...", NSStringFromProtocol(service));
        return;
    }
    
    //CheckClass
    if (![implClass conformsToProtocol:service]) {
        NSLog(@"🐝🐝 DHServiceManager:: implClass %@ doesn't comply with protocol %@...", NSStringFromClass(implClass), NSStringFromProtocol(service));
        return;
    }
    
    [self.lock lock];
    DHImplementObject *implObject = [DHImplementObject new];
    implObject.implementClass = implClass;
    [self.dicServiceProtocol setObject:implObject forKey:NSStringFromProtocol(service)];
    [self.lock unlock];
}
 
- (void)registerService:(Protocol *)service withStoryboard:(NSString *)storyboardName identifier:(NSString *)identifier
{
    if (service == nil || storyboardName == nil || identifier == nil) {
        NSLog(@"🐝🐝 DHServiceManager:: service and implClass must not be nil...");
        return;
    }
    
    id implClass = nil;
    
    @try {
        UIStoryboard *currentStoryboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
        implClass = [currentStoryboard instantiateViewControllerWithIdentifier:identifier];
    } @catch (NSException *exception) {
        NSString *errorMsg = @"🐝🐝 DHServiceManager:: storyboard not pair...";
        NSLog(@"%@", errorMsg);
        return;
        
    } @finally {
        
        //CheckClass
        if (![implClass conformsToProtocol:service]) {
            NSLog(@"🐝🐝 DHServiceManager:: implClass %@ doesn't comply with protocol %@...", NSStringFromClass(implClass), NSStringFromProtocol(service));
            return;
        }
        
        [self.lock lock];
        DHImplementObject *implObject = [DHImplementObject new];
        implObject.implementType = DHImplementTypeStoryboard;
        implObject.implementClass = implClass;
        implObject.storyboardName = storyboardName;
        implObject.storyboardIdentifier = identifier;
        [self.dicServiceProtocol setObject:implObject forKey:NSStringFromProtocol(service)];
        [self.lock unlock];
    }
}
 
- (id)implForService:(Protocol *)service
{
    if (service == nil ) {
        NSLog(@"🐝🐝 DHServiceManager:: service must not be nil...");
        return nil;
    }
    
    //CheckService
    if (![self isServiceRegisted:service]) {
        NSLog(@"🐝🐝 DHServiceManager:: %@, service has not been registed...", NSStringFromProtocol(service));
        return nil;
    }
    
    DHImplementObject *implObject = [self.dicServiceProtocol objectForKey:NSStringFromProtocol(service)];
    Class implClass = implObject.implementClass;
    
    if ([[implClass class] respondsToSelector:@selector(isSingleton)]) {
        if ([[implClass class] isSingleton]) {
            if ([[implClass class] respondsToSelector:@selector(sharedInstance)]) {
                return [[implClass class] sharedInstance];
            }
            
            return [[implClass alloc] init];
        }
    }
    
    if (implObject.implementType == DHImplementTypeStoryboard) {
        UIStoryboard *currentStoryboard = [UIStoryboard storyboardWithName:implObject.storyboardName bundle:nil];
        return [currentStoryboard instantiateViewControllerWithIdentifier:implObject.storyboardIdentifier];
    }
    
    return [[implClass alloc] init];
}
 
#pragma mark - Properties and private function
- (NSMutableDictionary *)dicServiceProtocol
{
    if (_dicServiceProtocol == nil) {
        _dicServiceProtocol = [[NSMutableDictionary alloc] init];
    }
    
    return _dicServiceProtocol;
}
 
- (NSRecursiveLock *)lock
{
    if (!_lock) {
        _lock = [[NSRecursiveLock alloc] init];
    }
    return _lock;
}
 
- (NSDictionary *)disServices
{
    [self.lock lock];
    NSDictionary *dict = [self.dicServiceProtocol copy];
    [self.lock unlock];
    return dict;
}
 
- (BOOL)isServiceRegisted:(Protocol *)service
{
    DHImplementObject *implObject = [[self disServices] objectForKey:NSStringFromProtocol(service)];
    Class class = implObject.implementClass;
    if (class) {
        return YES;
    }
    return NO;
}
@end