forked from Wtrwx/DYYY
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDYYYABTestHook.xm
195 lines (164 loc) · 5.58 KB
/
DYYYABTestHook.xm
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#import "DYYYABTestHook.h"
#import <objc/runtime.h>
// 声明ABTestManager接口
@interface AWEABTestManager : NSObject
@property(retain, nonatomic) NSDictionary *abTestData;
@property(retain, nonatomic) NSMutableDictionary *consistentABTestDic;
@property(copy, nonatomic) NSDictionary *performanceReversalDic;
- (void)setAbTestData:(id)arg1;
- (void)_saveABTestData:(id)arg1;
- (id)abTestData;
+ (id)sharedManager;
@end
// 全局变量实现
BOOL abTestBlockEnabled = NO;
NSDictionary *gFixedABTestData = nil;
dispatch_once_t onceToken;
BOOL gDataLoaded = NO;
static NSDate *lastLoadAttemptTime = nil;
static const NSTimeInterval kMinLoadInterval = 60.0;
// 从指定JSON文件加载ABTest数据,仅当需要时加载
void ensureABTestDataLoaded(void) {
if (gDataLoaded) return;
dispatch_once(&onceToken, ^{
// 获取Documents目录路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
// 修改为DYYY子文件夹下的路径
NSString *dyyyFolderPath = [documentsDirectory stringByAppendingPathComponent:@"DYYY"];
NSString *jsonFilePath = [dyyyFolderPath stringByAppendingPathComponent:@"abtest_data_fixed.json"];
// 确保DYYY目录存在
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:dyyyFolderPath]) {
NSError *error = nil;
[fileManager createDirectoryAtPath:dyyyFolderPath withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSLog(@"[DYYY] 创建DYYY目录失败: %@", error.localizedDescription);
}
}
NSError *error = nil;
NSData *jsonData = [NSData dataWithContentsOfFile:jsonFilePath options:0 error:&error];
if (jsonData) {
NSDictionary *loadedData = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:&error];
if (loadedData && !error) {
// 成功加载数据,保存到全局变量
gFixedABTestData = [loadedData copy];
gDataLoaded = YES;
return;
}
}
// 如果加载失败,使用空字典
gFixedABTestData = @{};
gDataLoaded = YES;
});
}
// 优化防止频繁加载
NSDictionary* loadFixedABTestData(void) {
// 检查是否已加载数据
if (gDataLoaded) {
return gFixedABTestData;
}
// 限制加载频率,避免短时间内多次尝试解析大型JSON
NSDate *now = [NSDate date];
if (lastLoadAttemptTime && [now timeIntervalSinceDate:lastLoadAttemptTime] < kMinLoadInterval) {
return gFixedABTestData;
}
// 更新最后尝试时间
lastLoadAttemptTime = now;
// 调用已有的加载函数
ensureABTestDataLoaded();
return gFixedABTestData;
}
// 替代空数据函数,返回固定数据 - 优化版本
static NSDictionary *fixedABTestData(void) {
// 如果禁用了热更新拦截,返回nil让原始实现处理
if (!abTestBlockEnabled) {
return nil;
}
// 延迟加载 - 仅当需要时才实际解析JSON
if (!gDataLoaded) {
ensureABTestDataLoaded();
}
return gFixedABTestData;
}
// 获取当前ABTest数据 - 优化版本
NSDictionary *getCurrentABTestData(void) {
// 如果启用了拦截且已加载固定数据,优先返回固定数据
if (abTestBlockEnabled) {
if (!gDataLoaded) {
ensureABTestDataLoaded();
}
return gFixedABTestData;
}
// 否则从Manager获取当前数据
AWEABTestManager *manager = [%c(AWEABTestManager) sharedManager];
if (!manager) {
return nil;
}
NSDictionary *currentData = [manager abTestData];
return currentData;
}
// 添加缓存策略
static NSMutableDictionary *gCaseCache = nil;
// Hook AWEABTestManager类
%hook AWEABTestManager
// 拦截获取 ABTest 数据的方法
- (id)abTestData {
if (!abTestBlockEnabled) {
return %orig;
}
// 延迟加载数据,仅当需要时才加载
if (!gDataLoaded) {
ensureABTestDataLoaded();
}
return gFixedABTestData ?: %orig;
}
// 拦截设置 ABTest 数据的方法
- (void)setAbTestData:(id)arg1 {
if (abTestBlockEnabled) {
return; // 禁用热更新时不执行
}
%orig;
}
// 拦截增量数据更新
- (void)incrementalUpdateData:(id)arg1 unchangedKeyList:(id)arg2 {
if (abTestBlockEnabled) {
return;
}
%orig;
}
// 拦截网络获取配置方法
- (void)fetchConfigurationWithRetry:(BOOL)arg1 completion:(id)arg2 {
if (abTestBlockEnabled) {
// 如果有完成回调,调用它但不更新数据
if (arg2 && [arg2 isKindOfClass:%c(NSBlock)]) {
dispatch_async(dispatch_get_main_queue(), ^{
((void (^)(id))arg2)(nil);
});
}
return;
}
%orig;
}
// 拦截另一个配置方法
- (void)fetchConfiguration:(id)arg1 {
if (abTestBlockEnabled) {
return;
}
%orig;
}
// 拦截重写ABTest数据的方法
- (void)overrideABTestData:(id)arg1 needCleanCache:(BOOL)arg2 {
if (abTestBlockEnabled) {
return;
}
%orig;
}
%end
%ctor {
// 初始化时加载设置
%init;
abTestBlockEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"ABTestBlockEnabled"];
}