Skip to content

Commit 0150ae4

Browse files
committed
优化地理位置获取逻辑,增加错误处理和回退机制;新增状态信息键
1 parent 702610f commit 0150ae4

File tree

3 files changed

+154
-45
lines changed

3 files changed

+154
-45
lines changed

CityManager.m

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -504,14 +504,19 @@ + (void)fetchLocationWithGeonameId:(NSString *)geonameId completionHandler:(void
504504
NSDictionary *status = jsonResult[@"status"];
505505
if (status && [status isKindOfClass:[NSDictionary class]]) {
506506
NSNumber *value = status[@"value"];
507-
// 检查 geonameId 是否存在的特定错误码 (value: 11)
508-
if (value && [value isEqualToNumber:@11]) {
509-
NSString *message = status[@"message"] ?: @"the geoname feature does not exist.";
510-
NSDictionary *userInfo = @{NSLocalizedDescriptionKey : message};
511-
NSError *apiError = [NSError errorWithDomain:DYYYGeonamesErrorDomain code:11 userInfo:userInfo];
512-
completionHandler(nil, apiError);
513-
return;
507+
NSInteger statusCode = value != nil ? value.integerValue : -1;
508+
NSString *message = status[@"message"] ?: @"the geoname feature does not exist.";
509+
510+
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
511+
userInfo[NSLocalizedDescriptionKey] = message;
512+
userInfo[DYYYGeonamesStatusUserInfoKey] = status;
513+
if (geonameId) {
514+
userInfo[@"geonameId"] = geonameId;
514515
}
516+
517+
NSError *apiError = [NSError errorWithDomain:DYYYGeonamesErrorDomain code:statusCode userInfo:userInfo];
518+
completionHandler(nil, apiError);
519+
return;
515520
}
516521

517522
completionHandler(jsonResult, nil);

DYYYConstants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
#define DYYY_REMOTE_MODE_STRING @"远程模式:启动时自动检查更新"
2020

2121
#define DYYYGeonamesErrorDomain @"com.dyyy.geonames.api.error"
22+
#define DYYYGeonamesStatusUserInfoKey @"com.dyyy.geonames.api.status"
2223

2324
#endif

DYYYUtils.m

Lines changed: 141 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,66 @@
99
#import "DYYYToast.h"
1010
#import "DYYYConstants.h"
1111

12+
@interface DYYYUtils ()
13+
+ (NSString *)fallbackLocationFromIPAttribution:(AWEAwemeModel *)model;
14+
+ (NSString *)displayLocationForGeoNamesError:(NSError *)error model:(AWEAwemeModel *)model;
15+
@end
16+
1217
@implementation DYYYUtils
1318

1419
static const void *kCurrentIPRequestCityCodeKey = &kCurrentIPRequestCityCodeKey;
1520

21+
static NSString *DYYYJSONStringFromObject(id object) {
22+
if (!object) {
23+
return nil;
24+
}
25+
if (![NSJSONSerialization isValidJSONObject:object]) {
26+
return nil;
27+
}
28+
29+
NSError *error = nil;
30+
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object options:0 error:&error];
31+
if (error || jsonData.length == 0) {
32+
return nil;
33+
}
34+
35+
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
36+
}
37+
38+
static void DYYYApplyDisplayLocationToLabel(UILabel *label, NSString *displayLocation, NSString *colorHexString) {
39+
if (!label) {
40+
return;
41+
}
42+
43+
NSString *resolvedLocation = displayLocation ?: @"";
44+
resolvedLocation = [resolvedLocation stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
45+
if (resolvedLocation.length == 0) {
46+
resolvedLocation = @"未知";
47+
}
48+
49+
NSString *currentLabelText = label.text ?: @"";
50+
NSString *newText = nil;
51+
NSRange ipRange = [currentLabelText rangeOfString:@"IP属地:"];
52+
if (ipRange.location != NSNotFound) {
53+
NSString *baseText = [currentLabelText substringToIndex:ipRange.location];
54+
newText = [NSString stringWithFormat:@"%@IP属地:%@", baseText, resolvedLocation];
55+
} else {
56+
if (currentLabelText.length > 0) {
57+
newText = [NSString stringWithFormat:@"%@ IP属地:%@", currentLabelText, resolvedLocation];
58+
} else {
59+
newText = [NSString stringWithFormat:@"IP属地:%@", resolvedLocation];
60+
}
61+
}
62+
63+
if (newText.length > 0 && ![label.text isEqualToString:newText]) {
64+
label.text = newText;
65+
} else if (label.text.length == 0) {
66+
label.text = newText;
67+
}
68+
69+
[DYYYUtils applyColorSettingsToLabel:label colorHexString:colorHexString];
70+
}
71+
1672
+ (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeModel *)model withLabelColor:(NSString *)colorHexString {
1773
NSString *originalText = label.text ?: @"";
1874
NSString *cityCode = model.cityCode;
@@ -73,43 +129,38 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
73129
displayLocation = localName;
74130
}
75131

132+
if (displayLocation.length == 0 || [displayLocation isEqualToString:@"未知"]) {
133+
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
134+
if (fallbackLocation.length > 0) {
135+
displayLocation = fallbackLocation;
136+
}
137+
}
138+
76139
dispatch_async(dispatch_get_main_queue(), ^{
77140
NSString *currentRequestCode = objc_getAssociatedObject(label, kCurrentIPRequestCityCodeKey);
78141
if (![currentRequestCode isEqualToString:cityCode]) {
79142
return;
80143
}
81144

82-
NSString *currentLabelText = label.text ?: @"";
83-
if ([currentLabelText containsString:@"IP属地:"]) {
84-
NSRange range = [currentLabelText rangeOfString:@"IP属地:"];
85-
if (range.location != NSNotFound) {
86-
NSString *baseText = [currentLabelText substringToIndex:range.location];
87-
if (![currentLabelText containsString:displayLocation]) {
88-
label.text = [NSString stringWithFormat:@"%@IP属地:%@", baseText, displayLocation];
89-
}
90-
}
91-
} else {
92-
if (currentLabelText.length > 0 && ![displayLocation isEqualToString:@"未知"]) {
93-
label.text = [NSString stringWithFormat:@"%@ IP属地:%@", currentLabelText, displayLocation];
94-
} else if (![displayLocation isEqualToString:@"未知"]) {
95-
label.text = [NSString stringWithFormat:@"IP属地:%@", displayLocation];
96-
}
97-
}
98-
[DYYYUtils applyColorSettingsToLabel:label colorHexString:colorHexString];
145+
DYYYApplyDisplayLocationToLabel(label, displayLocation, colorHexString);
99146
});
100147
} else {
101148
[CityManager fetchLocationWithGeonameId:cityCode
102149
completionHandler:^(NSDictionary *locationInfo, NSError *error) {
103150
__block NSString *displayLocation = @"未知";
104151

105152
if (error) {
106-
if ([error.domain isEqualToString:DYYYGeonamesErrorDomain] && error.code == 11) {
107-
displayLocation = error.localizedDescription;
153+
if ([error.domain isEqualToString:DYYYGeonamesErrorDomain]) {
154+
displayLocation = [DYYYUtils displayLocationForGeoNamesError:error model:model];
108155
} else {
109156
NSLog(@"[DYYY] GeoNames fetch failed: %@", error.localizedDescription);
110-
return;
157+
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
158+
if (fallbackLocation.length > 0) {
159+
displayLocation = fallbackLocation;
160+
}
111161
}
112162
} else if (locationInfo) {
163+
BOOL shouldCacheLocation = NO;
113164
NSString *countryName = locationInfo[@"countryName"];
114165
NSString *adminName1 = locationInfo[@"adminName1"];
115166
NSString *localName = locationInfo[@"name"];
@@ -122,11 +173,21 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
122173
} else {
123174
displayLocation = countryName;
124175
}
176+
shouldCacheLocation = YES;
125177
} else if (localName.length > 0) {
126178
displayLocation = localName;
179+
shouldCacheLocation = YES;
127180
}
128181

129-
if (![displayLocation isEqualToString:@"未知"]) {
182+
if (displayLocation.length == 0 || [displayLocation isEqualToString:@"未知"]) {
183+
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
184+
if (fallbackLocation.length > 0) {
185+
displayLocation = fallbackLocation;
186+
}
187+
shouldCacheLocation = NO;
188+
}
189+
190+
if (shouldCacheLocation && ![displayLocation isEqualToString:@"未知"]) {
130191
[geoNamesCache setObject:locationInfo forKey:cacheKey];
131192
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
132193
NSString *geoNamesCacheDir = [cachesDir stringByAppendingPathComponent:@"DYYYGeoNamesCache"];
@@ -141,23 +202,7 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
141202
return;
142203
}
143204

144-
NSString *currentLabelText = label.text ?: @"";
145-
if ([currentLabelText containsString:@"IP属地:"]) {
146-
NSRange range = [currentLabelText rangeOfString:@"IP属地:"];
147-
if (range.location != NSNotFound) {
148-
NSString *baseText = [currentLabelText substringToIndex:range.location];
149-
if (![currentLabelText containsString:displayLocation]) {
150-
label.text = [NSString stringWithFormat:@"%@IP属地:%@", baseText, displayLocation];
151-
}
152-
}
153-
} else {
154-
if (currentLabelText.length > 0 && ![displayLocation isEqualToString:@"未知"]) {
155-
label.text = [NSString stringWithFormat:@"%@ IP属地:%@", currentLabelText, displayLocation];
156-
} else if (![displayLocation isEqualToString:@"未知"]) {
157-
label.text = [NSString stringWithFormat:@"IP属地:%@", displayLocation];
158-
}
159-
}
160-
[DYYYUtils applyColorSettingsToLabel:label colorHexString:colorHexString];
205+
DYYYApplyDisplayLocationToLabel(label, displayLocation, colorHexString);
161206
});
162207
}];
163208
}
@@ -183,6 +228,64 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
183228
[DYYYUtils applyColorSettingsToLabel:label colorHexString:colorHexString];
184229
}
185230
}
231+
232+
+ (NSString *)fallbackLocationFromIPAttribution:(AWEAwemeModel *)model {
233+
if (!model) {
234+
return nil;
235+
}
236+
237+
NSString *rawAttribution = nil;
238+
@try {
239+
rawAttribution = model.ipAttribution;
240+
} @catch (NSException *exception) {
241+
return nil;
242+
}
243+
244+
if (![rawAttribution isKindOfClass:[NSString class]]) {
245+
return nil;
246+
}
247+
248+
NSString *trimmedValue = [rawAttribution stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
249+
if (trimmedValue.length == 0) {
250+
return nil;
251+
}
252+
253+
NSArray<NSString *> *prefixes = @[ @"IP属地:", @"IP属地:", @"IP 属地:", @"IP 属地:" ];
254+
for (NSString *prefix in prefixes) {
255+
if ([trimmedValue hasPrefix:prefix]) {
256+
trimmedValue = [trimmedValue substringFromIndex:prefix.length];
257+
break;
258+
}
259+
}
260+
261+
trimmedValue = [trimmedValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
262+
263+
return trimmedValue.length > 0 ? trimmedValue : nil;
264+
}
265+
266+
+ (NSString *)displayLocationForGeoNamesError:(NSError *)error model:(AWEAwemeModel *)model {
267+
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
268+
if (fallbackLocation.length > 0) {
269+
return fallbackLocation;
270+
}
271+
272+
NSDictionary *status = error.userInfo[DYYYGeonamesStatusUserInfoKey];
273+
if ([status isKindOfClass:[NSDictionary class]]) {
274+
NSString *statusJSON = DYYYJSONStringFromObject(@{ @"status" : status });
275+
if (statusJSON.length > 0) {
276+
return [NSString stringWithFormat:@"未知 %@", statusJSON];
277+
}
278+
}
279+
280+
NSString *message = error.localizedDescription ?: @"";
281+
message = [message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
282+
if (message.length > 0) {
283+
return [NSString stringWithFormat:@"未知 %@", message];
284+
}
285+
286+
return @"未知";
287+
}
288+
186289
#pragma mark - Public UI Utilities (公共 UI/窗口/控制器 工具)
187290

188291
+ (UIWindow *)getActiveWindow {

0 commit comments

Comments
 (0)