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
1419static 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