未验证 提交 ef0c2420 编写于 作者: M moliya 提交者: GitHub

feat(iOS): 新增JS脚本插件 (#1023)

* 新增JS脚本插件

* 优化页面切换效果

* update README
Co-authored-by: shang1962's avatarcarefree <946715806@qq.com>
上级 edea6791
......@@ -114,7 +114,8 @@ DoKit 是一个功能平台,能够让每一个 App 快速接入一些常用的
10. **【NSLog】** 把所有 NSLog 信息打印到UI界面,避免没有开发证书无法调试的尴尬;
11. **【Lumberjack】** 每一条 CocoaLumberjack 的日志信息,都在在 App 的界面中显示出来,再也不需要导出日志这么麻烦;(iOS独有)
12. **【DBView】** 通过网页方便快捷的操作应用内数据库,让数据库的调试变得非常优雅;
13. **【模拟弱网】** 限制网速,模拟弱网环境下App的运行情况。(android独有)
13. **【模拟弱网】** 限制网速,模拟弱网环境下App的运行情况;(android独有)
14. **【JS脚本】** 在指定WebView运行JS脚本。(iOS独有)
### 三、性能检测
......
......@@ -54,6 +54,7 @@ DoKit is rich in functions, easy to access, and easy to expand. Everyone is welc
* Log:print all logs to the UI interface for easy viewing
* UserDefaults(iOS): add, delete, and modify the NSUserDefaults file
* DBView:perform more detailed operations on the DB file on the web
* JavaScript(iOS):execute scripts in the web view
### Performance Tools
......
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "doraemon_js@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "doraemon_js@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -132,6 +132,15 @@
//UserDefaults
//JS脚本
"JS脚本" = "JavaScript";
"请选择WebView" = "Select WebView";
"无可用的WebView" = "No Available WebView";
"脚本列表" = "Script List";
"脚本执行" = "Execute Script";
"JS代码" = "JS Code";
"脚本不能为空" = "Code can not be empty";
//CocoaLumberjack
"Lumberjack" = "Lumberjack";
"CocoaLumberjack日志记录" = "CocoaLumberjack";
......
......@@ -132,6 +132,15 @@
//UserDefaults
//JS脚本
"JS脚本" = "JavaScript";
"请选择WebView" = "请选择WebView";
"无可用的WebView" = "无可用的WebView";
"脚本列表" = "脚本列表";
"脚本执行" = "脚本执行";
"JS代码" = "JS代码";
"脚本不能为空" = "脚本不能为空";
//CocoaLumberjack
"Lumberjack" = "Lumberjack";
"CocoaLumberjack日志记录" = "CocoaLumberjack日志记录";
......
......@@ -78,6 +78,12 @@
- (void)clearAllH5historicalRecord;
- (void)clearH5historicalRecordWithText:(NSString *)text;
/// JS历史脚本
- (NSArray<NSDictionary *> *)jsHistoricalRecord;
- (NSString *)jsHistoricalRecordForKey:(NSString *)key;
- (void)saveJsHistoricalRecordWithText:(NSString *)text forKey:(NSString *)key;
- (void)clearJsHistoricalRecordWithKey:(NSString *)key;
/// 保存启动类
- (void)saveStartClass : (NSString *)startClass;
- (NSString *)startClass;
......
......@@ -23,6 +23,7 @@ static NSString * const kDoraemonNSLogKey = @"doraemon_nslog_key";
static NSString * const kDoraemonMethodUseTimeKey = @"doraemon_method_use_time_key";
static NSString * const kDoraemonLargeImageDetectionKey = @"doraemon_large_image_detection_key";
static NSString * const kDoraemonH5historicalRecord = @"doraemon_historical_record";
static NSString * const kDoraemonJsHistoricalRecord = @"doraemon_js_historical_record";
static NSString * const kDoraemonStartTimeKey = @"doraemon_start_time_key";
static NSString * const kDoraemonStartClassKey = @"doraemon_start_class_key";
static NSString * const kDoraemonANRTrackKey = @"doraemon_anr_track_key";
......@@ -265,6 +266,68 @@ static NSString * const kDoraemonHealthStartKey = @"doraemon_health_start_key";
[_defaults synchronize];
}
- (NSArray<NSDictionary *> *)jsHistoricalRecord {
return [_defaults arrayForKey:kDoraemonJsHistoricalRecord];
}
- (NSString *)jsHistoricalRecordForKey:(NSString *)key {
NSArray *history = [self jsHistoricalRecord] ?: @[];
for (NSDictionary *dict in history) {
//是否同名配置
if ([[dict objectForKey:@"key"] isEqualToString:key]) {
return [dict objectForKey:@"value"];
}
}
return nil;
}
- (void)saveJsHistoricalRecordWithText:(NSString *)text forKey:(NSString *)key {
NSString *saveKey = [NSString stringWithFormat:@"%.0f", NSDate.date.timeIntervalSince1970];
if (key.length > 0) {
saveKey = key;
}
NSMutableArray *list = [NSMutableArray array];
BOOL matched = NO;
NSArray *history = [self jsHistoricalRecord] ?: @[];
for (NSDictionary *dict in history) {
//是否同名配置
if ([[dict objectForKey:@"key"] isEqualToString:saveKey]) {
[list addObject:@{
@"key": saveKey,
@"value": text
}];
matched = YES;
continue;
}
[list addObject:dict];
}
if (!matched) {
[list insertObject:@{
@"key": saveKey,
@"value": text
} atIndex:0];
}
[_defaults setObject:list forKey:kDoraemonJsHistoricalRecord];
[_defaults synchronize];
}
- (void)clearJsHistoricalRecordWithKey:(NSString *)key {
if (!key) {
return;
}
NSMutableArray *list = [NSMutableArray array];
NSArray *history = [self jsHistoricalRecord] ?: @[];
for (NSDictionary *dict in history) {
//是否同名配置
if ([[dict objectForKey:@"key"] isEqualToString:key]) {
continue;
}
[list addObject:dict];
}
[_defaults setObject:list forKey:kDoraemonJsHistoricalRecord];
[_defaults synchronize];
}
- (void)saveStartClass : (NSString *)startClass {
[_defaults setObject:startClass forKey:kDoraemonStartClassKey];
[_defaults synchronize];
......
......@@ -47,5 +47,7 @@
- (UIViewController *)doraemon_viewController;
- (NSArray *)doraemon_findViewsForClass:(Class)clazz;
@end
......@@ -124,4 +124,15 @@
return nil;
}
- (NSArray *)doraemon_findViewsForClass:(Class)clazz {
NSMutableArray *result = [NSMutableArray array];
for (UIView *subview in self.subviews) {
if ([subview isKindOfClass:clazz]) {
[result addObject:subview];
}
[result addObjectsFromArray:[subview doraemon_findViewsForClass:clazz]];
}
return result;
}
@end
......@@ -48,6 +48,8 @@ typedef NS_ENUM(NSUInteger, DoraemonManagerPluginType) {
DoraemonManagerPluginType_DoraemonDatabasePlugin,
// NSUserDefaults工具
DoraemonManagerPluginType_DoraemonNSUserDefaultsPlugin,
// JS脚本
DoraemonManagerPluginType_DoraemonJavaScriptPlugin,
#pragma mark - 性能检测
// 帧率监控
......
......@@ -242,6 +242,7 @@ typedef void (^DoraemonPerformanceBlock)(NSDictionary *);
#if DoraemonWithDatabase
[self addPluginWithPluginType:DoraemonManagerPluginType_DoraemonDatabasePlugin];
#endif
[self addPluginWithPluginType:DoraemonManagerPluginType_DoraemonJavaScriptPlugin];
#pragma mark - 性能检测
[self addPluginWithPluginType:DoraemonManagerPluginType_DoraemonFPSPlugin];
......@@ -570,6 +571,14 @@ typedef void (^DoraemonPerformanceBlock)(NSDictionary *);
@{kAtModule:DoraemonLocalizedString(@"常用工具")},
@{kBuriedPoint:@"dokit_sdk_comm_ck_userdefault"}
],
@(DoraemonManagerPluginType_DoraemonJavaScriptPlugin) : @[
@{kTitle:DoraemonLocalizedString(@"JS脚本")},
@{kDesc:DoraemonLocalizedString(@"JS脚本")},
@{kIcon:@"doraemon_js"},
@{kPluginName:@"DoraemonJavaScriptPlugin"},
@{kAtModule:DoraemonLocalizedString(@"常用工具")},
@{kBuriedPoint:@"dokit_sdk_comm_ck_js"}
],
// 性能检测
@(DoraemonManagerPluginType_DoraemonFPSPlugin) : @[
......
//
// DoraemonJavaScriptDetailViewController.h
// DoraemonKit
//
// Created by carefree on 2022/5/11.
//
#import "DoraemonBaseViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface DoraemonJavaScriptDetailViewController : DoraemonBaseViewController
@property (nonatomic, copy) NSString *key;
@end
NS_ASSUME_NONNULL_END
//
// DoraemonJavaScriptDetailViewController.m
// DoraemonKit
//
// Created by carefree on 2022/5/11.
//
#import "DoraemonJavaScriptDetailViewController.h"
#import "DoraemonKit.h"
#import "DoraemonDefine.h"
#import "DoraemonToastUtil.h"
#import "DoraemonCacheManager.h"
#import "DoraemonJavaScriptManager.h"
@interface DoraemonJavaScriptDetailViewController ()
@property (nonatomic, weak) UITextView *textView;
@end
@implementation DoraemonJavaScriptDetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = DoraemonLocalizedString(@"脚本执行");
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(runScript)];
UIEdgeInsets edge = UIEdgeInsetsMake(10, 10, 0, 10);
CGFloat width = self.view.bounds.size.width - edge.left - edge.right;
CGFloat height = self.view.bounds.size.height - edge.top - edge.bottom;
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(edge.left, edge.top + IPHONE_NAVIGATIONBAR_HEIGHT, width, 30)];
titleLabel.text = DoraemonLocalizedString(@"JS代码");
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(edge.left, CGRectGetMaxY(titleLabel.frame) + edge.top, width, height - 200)];
textView.layer.borderWidth = 1 / UIScreen.mainScreen.scale;
textView.layer.borderColor = [[UIColor lightGrayColor] CGColor];
textView.layer.cornerRadius = 6;
textView.font = [UIFont systemFontOfSize:16];
textView.textContainerInset = UIEdgeInsetsMake(8, 3, 8, 3);
[self.view addSubview:titleLabel];
[self.view addSubview:textView];
self.textView = textView;
if (self.key.length > 0) {
self.textView.text = [DoraemonCacheManager.sharedInstance jsHistoricalRecordForKey:self.key];
}
}
#pragma mark - Private
- (void)runScript {
NSString *value = self.textView.text;
if (value.length == 0) {
[DoraemonToastUtil showToastBlack:@"脚本不能为空" inView:self.view];
return;
}
[DoraemonCacheManager.sharedInstance saveJsHistoricalRecordWithText:value forKey:self.key];
[DoraemonManager.shareInstance hiddenHomeWindow];
[DoraemonJavaScriptManager.shareInstance evalJavaScript:value];
}
@end
//
// DoraemonJavaScriptPlugin.h
// AFNetworking
//
// Created by carefree on 2022/5/11.
//
#import <Foundation/Foundation.h>
#import "DoraemonPluginProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface DoraemonJavaScriptPlugin : NSObject<DoraemonPluginProtocol>
@end
NS_ASSUME_NONNULL_END
//
// DoraemonJavaScriptPlugin.m
// AFNetworking
//
// Created by carefree on 2022/5/11.
//
#import "DoraemonJavaScriptPlugin.h"
#import "DoraemonJavaScriptManager.h"
#import "DoraemonHomeWindow.h"
@implementation DoraemonJavaScriptPlugin
- (void)pluginDidLoad {
[[DoraemonHomeWindow shareInstance] hide];
[[DoraemonJavaScriptManager shareInstance] show];
}
@end
//
// DoraemonJavaScriptViewController.h
// DoraemonKit
//
// Created by carefree on 2022/5/11.
//
#import "DoraemonBaseViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface DoraemonJavaScriptViewController : DoraemonBaseViewController
@end
NS_ASSUME_NONNULL_END
//
// DoraemonJavaScriptViewController.m
// DoraemonKit
//
// Created by carefree on 2022/5/11.
//
#import "DoraemonJavaScriptViewController.h"
#import "DoraemonJavaScriptDetailViewController.h"
#import "DoraemonCacheManager.h"
#import "DoraemonDefine.h"
@interface DoraemonJavaScriptViewController ()<UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, weak) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *items;
@end
@implementation DoraemonJavaScriptViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = DoraemonLocalizedString(@"脚本列表");
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addNewScript)];
self.items = [NSMutableArray array];
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
tableView.rowHeight = 100;
[self.view addSubview:tableView];
self.tableView = tableView;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self loadScriptData];
[self.tableView reloadData];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"];
}
cell.textLabel.text = [self.items[indexPath.row] objectForKey:@"value"];
cell.textLabel.numberOfLines = 4;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
DoraemonJavaScriptDetailViewController *detailVC = [[DoraemonJavaScriptDetailViewController alloc] init];
detailVC.key = [self.items[indexPath.row] objectForKey:@"key"];
[self.navigationController pushViewController:detailVC animated:YES];
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSString *key = [self.items[indexPath.row] objectForKey:@"key"];
[DoraemonCacheManager.sharedInstance clearJsHistoricalRecordWithKey:key];
[self loadScriptData];
[self.tableView reloadData];
}
}
#pragma mark - Private
- (void)addNewScript {
DoraemonJavaScriptDetailViewController *detailVC = [[DoraemonJavaScriptDetailViewController alloc] init];
[self.navigationController pushViewController:detailVC animated:YES];
}
- (void)loadScriptData {
[self.items removeAllObjects];
//读取历史数据
NSArray *scriptItems = [DoraemonCacheManager.sharedInstance jsHistoricalRecord];
if (!scriptItems) {
//添加内置脚本
[DoraemonCacheManager.sharedInstance saveJsHistoricalRecordWithText:@"//安装vConsole\nimport('https://unpkg.com/vconsole').then(() => {\n new window.VConsole()\n})" forKey:@"vConsole"];
[DoraemonCacheManager.sharedInstance saveJsHistoricalRecordWithText:@"//重新加载\nlocation.reload()" forKey:@"Reload"];
[DoraemonCacheManager.sharedInstance saveJsHistoricalRecordWithText:@"//后退\nhistory.go(-1)" forKey:@"Back"];
[DoraemonCacheManager.sharedInstance saveJsHistoricalRecordWithText:@"//前进\nhistory.go(1)" forKey:@"Forward"];
scriptItems = [DoraemonCacheManager.sharedInstance jsHistoricalRecord];
}
[self.items addObjectsFromArray:scriptItems];
}
@end
//
// DoraemonJavaScriptManager.h
// DoraemonKit
//
// Created by carefree on 2022/5/11.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface DoraemonJavaScriptManager : NSObject
+ (DoraemonJavaScriptManager *)shareInstance;
- (void)show;
- (void)evalJavaScript:(NSString *)script;
@end
NS_ASSUME_NONNULL_END
//
// DoraemonJavaScriptManager.m
// DoraemonKit
//
// Created by carefree on 2022/5/11.
//
#import "DoraemonJavaScriptManager.h"
#import <WebKit/WebKit.h>
#import "DoraemonDefine.h"
#import "DoraemonHomeWindow.h"
#import "UIViewController+Doraemon.h"
#import "DoraemonJavaScriptViewController.h"
@interface DoraemonJavaScriptManager ()
@property (nonatomic, weak) id webView;
@end
@implementation DoraemonJavaScriptManager
+ (DoraemonJavaScriptManager *)shareInstance{
static dispatch_once_t once;
static DoraemonJavaScriptManager *instance;
dispatch_once(&once, ^{
instance = [[DoraemonJavaScriptManager alloc] init];
});
return instance;
}
- (void)show {
NSArray *webViews = [DoraemonUtil getWebViews];
NSString *title = DoraemonLocalizedString(@"请选择WebView");
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:title preferredStyle:UIAlertControllerStyleActionSheet];
for (NSInteger i = 0; i < webViews.count; i++) {
WKWebView *webView = webViews[i];
NSString *actionTitle = webView.description;
UIAlertAction *action = [UIAlertAction actionWithTitle:actionTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self selectWebView:webView];
}];
[alert addAction:action];
}
if (webViews.count == 0) {
UIAlertAction *action = [UIAlertAction actionWithTitle:DoraemonLocalizedString(@"无可用的WebView") style:UIAlertActionStyleDestructive handler:nil];
action.enabled = NO;
[alert addAction:action];
}
if (webViews.count == 1) {
//只有一个,则跳过选择
[self selectWebView:webViews.firstObject];
return;
}
[alert addAction:[UIAlertAction actionWithTitle:DoraemonLocalizedString(@"取消") style:UIAlertActionStyleCancel handler:nil]];
dispatch_async(dispatch_get_main_queue(), ^{
[UIViewController.topViewControllerForKeyWindow presentViewController:alert animated:YES completion:nil];
});
}
- (void)selectWebView:(id)webView {
self.webView = webView;
DoraemonJavaScriptViewController *vc = [[DoraemonJavaScriptViewController alloc] init];
[DoraemonHomeWindow openPlugin:vc];
}
- (void)evalJavaScript:(NSString *)script {
id currentWebView = self.webView;
if (!currentWebView) {
return;
}
if ([currentWebView isKindOfClass:WKWebView.class]) {
WKWebView *webView = currentWebView;
[webView evaluateJavaScript:script completionHandler:^(id _Nullable result, NSError * _Nullable error) {
if (error) {
NSLog(@"js error: %@", error);
}
}];
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if ([currentWebView isKindOfClass:UIWebView.class]) {
UIWebView *webView = currentWebView;
[webView stringByEvaluatingJavaScriptFromString:script];
}
#pragma clang diagnostic pop
}
@end
......@@ -55,6 +55,8 @@
+ (UIWindow *)getKeyWindow;
+ (NSArray *)getWebViews;
+ (void)openPlugin:(UIViewController *)vc __attribute__((deprecated("此方法已弃用,请使用[DoraemonHomeWindow openPlugin:vc];")));
+ (UIViewController *)rootViewControllerForKeyWindow __attribute__((deprecated("此方法已弃用,请使用[UIViewController rootViewControllerForKeyWindow]")));
......
......@@ -7,6 +7,7 @@
//
#import "DoraemonUtil.h"
#import <WebKit/WebKit.h>
#import "UIViewController+Doraemon.h"
#import "DoraemonHomeWindow.h"
#import "DoraemonAppInfoUtil.h"
......@@ -310,4 +311,15 @@
return keyWindow;
}
+ (NSArray *)getWebViews {
NSMutableArray *webViews = [NSMutableArray array];
// 查找当前window中的所有webView
[webViews addObjectsFromArray:[[self getKeyWindow] doraemon_findViewsForClass:WKWebView.class]];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[webViews addObjectsFromArray:[[self getKeyWindow] doraemon_findViewsForClass:UIWebView.class]];
#pragma clang diagnostic pop
return webViews;
}
@end
......@@ -37,7 +37,7 @@
NSString *url = @"http://www.dokit.cn/";
url = [NSString stringWithFormat:@"%@%@",url, api];
[manager POST:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
[manager POST:url parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
if (sus) {
sus(responseObject);
}
......@@ -77,7 +77,7 @@
url = [NSString stringWithFormat:@"%@%@",url, api];
[manager GET:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
[manager GET:url parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
if (sus) {
sus(responseObject);
}
......
......@@ -65,6 +65,7 @@
[[DoraemonManager shareInstance] addH5DoorBlock:^(NSString *h5Url) {
NSLog(@"使用自带容器打开H5链接: %@",h5Url);
}];
[[DoraemonManager shareInstance] addWebpHandleBlock:^UIImage * _Nullable(NSString * _Nonnull filePath) {
......
......@@ -21,32 +21,31 @@ PODS:
- CocoaLumberjack (3.7.2):
- CocoaLumberjack/Core (= 3.7.2)
- CocoaLumberjack/Core (3.7.2)
- DoraemonKit/Core (3.0.8):
- DoraemonKit/Core (3.1.2):
- AFNetworking
- FMDB
- GCDWebServer
- GCDWebServer/WebDAV
- GCDWebServer/WebUploader
- DoraemonKit/WithDatabase (3.0.8):
- DoraemonKit/WithDatabase (3.1.2):
- DoraemonKit/Core
- YYDebugDatabase
- DoraemonKit/WithGPS (3.0.8):
- DoraemonKit/WithGPS (3.1.2):
- DoraemonKit/Core
- DoraemonKit/WithLoad (3.0.8):
- DoraemonKit/WithLoad (3.1.2):
- DoraemonKit/Core
- DoraemonKit/WithLogger (3.0.8):
- DoraemonKit/WithLogger (3.1.2):
- CocoaLumberjack
- DoraemonKit/Core
- DoraemonKit/WithMLeaksFinder (3.0.8):
- DoraemonKit/WithMLeaksFinder (3.1.2):
- DoraemonKit/Core
- FBRetainCycleDetector
- DoraemonKit/WithMultiControl (3.0.8):
- AFNetworking
- DoraemonKit/WithMultiControl (3.1.2):
- CocoaHTTPServer
- CocoaLumberjack
- DoraemonKit/Core
- SocketRocket
- DoraemonKit/WithWeex (3.0.8):
- DoraemonKit/WithWeex (3.1.2):
- DoraemonKit/Core
- WeexSDK
- WXDevtool
......@@ -140,12 +139,12 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
CocoaHTTPServer: 5624681fc3473d43b18202f635f9b3abb013b530
CocoaLumberjack: b7e05132ff94f6ae4dfa9d5bce9141893a21d9da
DoraemonKit: 8df7d459f2af3da8e71a55fadf2d5d686551e79d
DoraemonKit: aa228d6cc263888f68dab6bd14507657397474c1
FBRetainCycleDetector: 46daef95c2dfa9be34b53087edf6a8f34e4c749c
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4
JSONModel: 02ab723958366a3fd27da57ea2af2113658762e9
libwebp: 9c174486ec18a564cf0ecea2adcc85d10968ff98
libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3
Masonry: ff105a956abcd19a618b2028b121cb638d7a8e2f
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: f56ab499e3ea57dfeb6c3187dce183b10e160db0
......@@ -156,4 +155,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: eb4dd1e6c68fe5acfa519a16e30fff7583e1ea69
COCOAPODS: 1.10.2
COCOAPODS: 1.11.3
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册