Skip to content

Commit 4faf645

Browse files
authored
feat(iOS): Complete multi-control data mock module. (#1031)
* fix(iOS): Device registration happen a duplication. * fix(iOS): Call QR scan completion handler after dismiss/pop scan view controller. * chore(iOS): Refactor project structure. * feat(iOS): Complete DoKit Studio connect logic. * fix(iOS): Add WebSocket manager state change logic. * feat(iOS): Complete multi-control data mock module.
1 parent 34ec6c3 commit 4faf645

34 files changed

+1177
-97
lines changed

DoraemonKit.podspec

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,35 @@ iOS各式各样的工具集合
3434
'DEFINES_MODULE' => 'YES'
3535
}
3636

37-
s.subspec 'Foundation' do |ss|
38-
ss.source_files = 'iOS/DoKit/Classes/Foundation/*.{h,c}'
37+
s.subspec 'CFoundation' do |ss|
38+
ss.source_files = 'iOS/DoKit/Classes/CFoundation/*.{h,c}'
3939
ss.compiler_flags = '-Wall', '-Wextra', '-Wpedantic', '-Werror', '-fvisibility=hidden'
4040
end
4141

42-
s.subspec 'CoreNG' do |ss|
43-
ss.dependency 'DoraemonKit/Foundation'
44-
ss.source_files = 'iOS/DoKit/Classes/Core/**/*.{h,m}'
42+
s.subspec 'Foundation' do |ss|
43+
ss.source_files = 'iOS/DoKit/Classes/Foundation/**/*.{h,m}'
4544
# language-extension-token warning be used to implement Objective-C typeof().
4645
# ?: grammar
4746
ss.compiler_flags = '-Wall', '-Wextra', '-Wpedantic', '-Werror', '-Wno-language-extension-token', '-Wno-gnu-conditional-omitted-operand'
48-
ss.resource_bundle = {
49-
'DoKitResource' => [
50-
'iOS/DoKit/Assets/Assets.xcassets',
51-
'iOS/DoKit/Assets/*.xib'
52-
]
53-
}
5447
ss.dependency 'SocketRocket', '~> 0.6'
5548
ss.dependency 'Mantle', '~> 2.2'
5649
end
50+
51+
# s.subspec 'CoreNG' do |ss|
52+
# ss.dependency 'DoraemonKit/Foundation'
53+
# ss.source_files = 'iOS/DoKit/Classes/Core/**/*.{h,m}'
54+
# # language-extension-token warning be used to implement Objective-C typeof().
55+
# # ?: grammar
56+
# ss.compiler_flags = '-Wall', '-Wextra', '-Wpedantic', '-Werror', '-Wno-language-extension-token', '-Wno-gnu-conditional-omitted-operand'
57+
# ss.resource_bundle = {
58+
# 'DoKitResource' => [
59+
# 'iOS/DoKit/Assets/Assets.xcassets',
60+
# 'iOS/DoKit/Assets/*.xib'
61+
# ]
62+
# }
63+
# ss.dependency 'SocketRocket', '~> 0.6'
64+
# ss.dependency 'Mantle', '~> 2.2'
65+
# end
5766

5867
s.subspec 'EventSynthesize' do |ss|
5968
ss.source_files = 'iOS/DoKit/Classes/EventSynthesize/*.{h,m}'
@@ -72,6 +81,7 @@ iOS各式各样的工具集合
7281
ss.dependency 'GCDWebServer/WebDAV'
7382
ss.dependency 'FMDB'
7483
ss.dependency 'AFNetworking'
84+
ss.dependency 'JSONModel'
7585
end
7686

7787
s.subspec 'WithLogger' do |ss|
@@ -136,8 +146,11 @@ iOS各式各样的工具集合
136146
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) DoraemonWithMultiControl'
137147
}
138148
ss.dependency 'DoraemonKit/Core'
149+
ss.dependency 'DoraemonKit/Foundation'
139150
ss.dependency 'CocoaLumberjack'
140151
ss.dependency 'CocoaHTTPServer'
141152
ss.dependency 'SocketRocket'
153+
ss.dependency 'Masonry'
154+
ss.dependency 'AFNetworking', '~> 3.0'
142155
end
143156
end

iOS/Demo.xcodeproj/project.pbxproj

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
18C7CAAC26FB5F8D00A47F7C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 18C7CAAA26FB5F8D00A47F7C /* Main.storyboard */; };
1313
18C7CAAE26FB5F8F00A47F7C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18C7CAAD26FB5F8F00A47F7C /* Assets.xcassets */; };
1414
18C7CAB126FB5F8F00A47F7C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 18C7CAAF26FB5F8F00A47F7C /* LaunchScreen.storyboard */; };
15-
8BFA0A4D8625F5F35983C2FF /* Pods_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF31F4800187AA43EF17C9AB /* Pods_Demo.framework */; };
15+
FF6F1A3FA338925D5551ADB6 /* libPods-Demo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D44C18175B75199F625E8EC7 /* libPods-Demo.a */; };
1616
/* End PBXBuildFile section */
1717

1818
/* Begin PBXFileReference section */
@@ -24,7 +24,7 @@
2424
18C7CAAD26FB5F8F00A47F7C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
2525
18C7CAB026FB5F8F00A47F7C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
2626
18C7CAB226FB5F8F00A47F7C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
27-
AF31F4800187AA43EF17C9AB /* Pods_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
27+
D44C18175B75199F625E8EC7 /* libPods-Demo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Demo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
2828
EC6833A07F0818E63D44A2B9 /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.debug.xcconfig"; path = "Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig"; sourceTree = "<group>"; };
2929
/* End PBXFileReference section */
3030

@@ -33,7 +33,7 @@
3333
isa = PBXFrameworksBuildPhase;
3434
buildActionMask = 2147483647;
3535
files = (
36-
8BFA0A4D8625F5F35983C2FF /* Pods_Demo.framework in Frameworks */,
36+
FF6F1A3FA338925D5551ADB6 /* libPods-Demo.a in Frameworks */,
3737
);
3838
runOnlyForDeploymentPostprocessing = 0;
3939
};
@@ -74,7 +74,7 @@
7474
617A36452BCE105D0FCFECEA /* Frameworks */ = {
7575
isa = PBXGroup;
7676
children = (
77-
AF31F4800187AA43EF17C9AB /* Pods_Demo.framework */,
77+
D44C18175B75199F625E8EC7 /* libPods-Demo.a */,
7878
);
7979
name = Frameworks;
8080
sourceTree = "<group>";
@@ -99,7 +99,7 @@
9999
18C7CA9D26FB5F8D00A47F7C /* Sources */,
100100
18C7CA9E26FB5F8D00A47F7C /* Frameworks */,
101101
18C7CA9F26FB5F8D00A47F7C /* Resources */,
102-
01A57AFE85E4AC1011E9F44A /* [CP] Embed Pods Frameworks */,
102+
3F213C27944A91E0968B026B /* [CP] Copy Pods Resources */,
103103
);
104104
buildRules = (
105105
);
@@ -157,21 +157,21 @@
157157
/* End PBXResourcesBuildPhase section */
158158

159159
/* Begin PBXShellScriptBuildPhase section */
160-
01A57AFE85E4AC1011E9F44A /* [CP] Embed Pods Frameworks */ = {
160+
3F213C27944A91E0968B026B /* [CP] Copy Pods Resources */ = {
161161
isa = PBXShellScriptBuildPhase;
162162
buildActionMask = 2147483647;
163163
files = (
164164
);
165165
inputFileListPaths = (
166-
"${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-frameworks-${CONFIGURATION}-input-files.xcfilelist",
166+
"${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-resources-${CONFIGURATION}-input-files.xcfilelist",
167167
);
168-
name = "[CP] Embed Pods Frameworks";
168+
name = "[CP] Copy Pods Resources";
169169
outputFileListPaths = (
170-
"${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-frameworks-${CONFIGURATION}-output-files.xcfilelist",
170+
"${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-resources-${CONFIGURATION}-output-files.xcfilelist",
171171
);
172172
runOnlyForDeploymentPostprocessing = 0;
173173
shellPath = /bin/sh;
174-
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh\"\n";
174+
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-resources.sh\"\n";
175175
showEnvVarsInLog = 0;
176176
};
177177
4D41A223381189A234AE62A7 /* [CP] Check Pods Manifest.lock */ = {

iOS/Demo/AppDelegate.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import DoraemonKit
1919

2020
@main
2121
private class AppDelegate: UIResponder, UIApplicationDelegate {
22-
22+
2323
var window: UIWindow?
2424

2525
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
2626
// Override point for customization after application launch.
27-
DoKit.install(withProductId: nil)
28-
27+
DoraemonManager.shareInstance().install()
28+
2929
return true
3030
}
3131

iOS/Demo/Info.plist

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
4-
<dict>
5-
<key>NSAppTransportSecurity</key>
6-
<dict>
7-
<key>NSAllowsLocalNetworking</key>
8-
<true/>
9-
</dict>
10-
</dict>
4+
<dict/>
115
</plist>

iOS/Demo/ViewController.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515
*/
1616

1717
import UIKit
18-
import DoraemonKit
18+
//import DoraemonKit
1919

2020
class ViewController: UIViewController {
21-
21+
22+
// var networkManager: DKWebSocketSession? = nil
23+
2224
override func viewDidLoad() {
2325
super.viewDidLoad()
2426
// Do any additional setup after loading the view.
25-
DoKit.install(withProductId: nil)
27+
// networkManager = DKWebSocketSession(url: URL(string: "ws://172.23.161.126:8000/proxy/multicontrol/EYUHLKMG")!)
2628
}
27-
29+
2830
}

iOS/DoKit/Classes/Core/DTO/DKLoginDataDTOModel.m renamed to iOS/DoKit/Classes/Foundation/DKMultiControlProtocol.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17-
#import "DKLoginDataDTOModel.h"
17+
#import <Foundation/Foundation.h>
1818

19-
@implementation DKLoginDataDTOModel
19+
NS_ASSUME_NONNULL_BEGIN
2020

21-
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
22-
return @{
23-
@"manufacturer": @"manufacturer",
24-
@"connectSerial": @"connectSerial"
25-
};
26-
}
21+
@interface DKMultiControlProtocol : NSURLProtocol
2722

2823
@end
24+
25+
NS_ASSUME_NONNULL_END
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/**
2+
* Copyright 2017 Beijing DiDi Infinity Technology and Development Co., Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "DKMultiControlProtocol.h"
18+
#import <DoraemonKit/DKMultiControlStreamManager.h>
19+
20+
NS_ASSUME_NONNULL_BEGIN
21+
22+
static NSString *const ERROR_DOMAIN = @"com.didi.dokit";
23+
24+
static NSString *const MULTI_CONTROL_PROTOCOL_KEY = @"MULTI_CONTROL_PROTOCOL_KEY";
25+
26+
@interface DKMultiControlProtocol () <NSURLSessionDataDelegate>
27+
28+
@property(nonatomic, nullable, weak) NSURLSession *urlSession;
29+
30+
@property(nonatomic, nullable, copy) NSString *dataId;
31+
32+
@property(nonatomic, nullable, copy) NSHTTPURLResponse *httpUrlResponse;
33+
34+
@property(nonatomic, nullable, copy) NSString *responseBody;
35+
36+
@end
37+
38+
NS_ASSUME_NONNULL_END
39+
40+
@implementation DKMultiControlProtocol
41+
42+
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
43+
// +[NSURLProtocol canInitWithRequest:] may be called from any thread.
44+
BOOL returnValue = NO;
45+
switch (DKMultiControlStreamManager.sharedInstance.state) {
46+
case DKMultiControlStreamManagerStateMaster:
47+
if (![NSURLProtocol propertyForKey:MULTI_CONTROL_PROTOCOL_KEY inRequest:request]) {
48+
NSString *contentType = [request valueForHTTPHeaderField:@"Content-Type"];
49+
NSString *accept = [request valueForHTTPHeaderField:@"Accept"];
50+
if (![contentType hasPrefix:@"multipart/form-data"] && ![accept hasPrefix:@"image/"]) {
51+
returnValue = YES;
52+
}
53+
}
54+
break;
55+
case DKMultiControlStreamManagerStateSlave:
56+
returnValue = YES;
57+
break;
58+
59+
default:
60+
break;
61+
}
62+
63+
return returnValue;
64+
}
65+
66+
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
67+
// +[NSURLProtocol canonicalRequestForRequest:] may be called from any thread.
68+
NSURLRequest *result = request;
69+
switch (DKMultiControlStreamManager.sharedInstance.state) {
70+
case DKMultiControlStreamManagerStateMaster: {
71+
NSMutableURLRequest *mutableUrlRequest = result.mutableCopy;
72+
[NSURLProtocol setProperty:@(YES) forKey:MULTI_CONTROL_PROTOCOL_KEY inRequest:mutableUrlRequest];
73+
result = mutableUrlRequest.copy;
74+
}
75+
break;
76+
77+
default:
78+
break;
79+
}
80+
81+
return result;
82+
}
83+
84+
- (void)startLoading {
85+
NSOperationQueue *clientOperationQueue = [[NSOperationQueue alloc] init];
86+
clientOperationQueue.maxConcurrentOperationCount = 1;
87+
if ([NSURLProtocol propertyForKey:MULTI_CONTROL_PROTOCOL_KEY inRequest:self.request]) {
88+
self.urlSession = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration delegate:self delegateQueue:clientOperationQueue];
89+
[[self.urlSession dataTaskWithRequest:self.request] resume];
90+
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
91+
dispatch_async(dispatch_get_main_queue(), ^{
92+
self.dataId = [DKMultiControlStreamManager.sharedInstance recordWithUrlRequest:self.request];
93+
dispatch_semaphore_signal(semaphore);
94+
});
95+
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
96+
} else {
97+
// Slave device send request through websocket.
98+
NSURLRequest *urlRequest = self.request.copy;
99+
__weak typeof(self) weakSelf = self;
100+
dispatch_async(dispatch_get_main_queue(), ^{
101+
[DKMultiControlStreamManager.sharedInstance queryWithUrlRequest:urlRequest completionBlock:^(NSError *error, NSHTTPURLResponse *response, NSData *data) {
102+
// Main thread.
103+
[clientOperationQueue addOperationWithBlock:^{
104+
typeof(weakSelf) self = weakSelf;
105+
if (error || !response) {
106+
[self.client URLProtocol:self didFailWithError:error ?: [NSError errorWithDomain:ERROR_DOMAIN code:0 userInfo:nil]];
107+
108+
return;
109+
}
110+
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
111+
if (data) {
112+
[self.client URLProtocol:self didLoadData:data];
113+
}
114+
[self.client URLProtocolDidFinishLoading:self];
115+
}];
116+
}];
117+
});
118+
}
119+
}
120+
121+
- (void)stopLoading {
122+
[self.urlSession invalidateAndCancel];
123+
}
124+
125+
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
126+
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
127+
completionHandler(NSURLSessionResponseAllow);
128+
if ([response isKindOfClass:NSHTTPURLResponse.class]) {
129+
self.httpUrlResponse = (NSHTTPURLResponse *) response;
130+
}
131+
}
132+
133+
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
134+
[self.client URLProtocol:self didLoadData:data];
135+
// TODO(ChasonTang): Append data to `self.responseData`.
136+
self.responseBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
137+
}
138+
139+
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
140+
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
141+
NSURLCredential *urlCredential = challenge.protectionSpace.serverTrust ? [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] : nil;
142+
completionHandler(NSURLSessionAuthChallengeUseCredential, urlCredential);
143+
} else {
144+
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
145+
}
146+
}
147+
148+
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
149+
if (!error) {
150+
[self.client URLProtocolDidFinishLoading:self];
151+
if (self.httpUrlResponse && self.dataId) {
152+
NSHTTPURLResponse *httpUrlResponse = self.httpUrlResponse.copy;
153+
NSString *dataId = self.dataId.copy;
154+
NSString *responseBody = self.responseBody.copy;
155+
dispatch_async(dispatch_get_main_queue(), ^{
156+
[DKMultiControlStreamManager.sharedInstance recordWithHTTPUrlResponse:httpUrlResponse dataId:dataId responseBody:responseBody];
157+
});
158+
}
159+
} else {
160+
[self.client URLProtocol:self didFailWithError:error];
161+
}
162+
}
163+
164+
@end

0 commit comments

Comments
 (0)